//1 ScrollBarCtl.h
#include <vector>
// CScrollBarCtl
class CScrollBarCtl : public CWnd
{
DECLARE_DYNAMIC(CScrollBarCtl)
public:
CScrollBarCtl();
virtual ~CScrollBarCtl();
void addText(CString str);
//框架虚函数
protected:
virtual BOOL PreTranslateMessage(MSG* pMsg);
//框架消息
protected:
afx_msg void OnPaint();
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
protected:
void RectifyControl( int cx, int cy );
DECLARE_MESSAGE_MAP()
private:
INT m_nMaxPels; //滚动范围
INT m_nPagePels; //页面大小
INT m_nCurrentPos; //当前位置
INT m_nLineCount; //行数
CFont m_font;
std::vector<CString> m_logisticsList;
};
//2 ScrollBarCtl.cpp
#include "ScrollBarCtl.h"
#define LINE_PELS 12
#define WHELL_PELS 5
#define LINE_INTERVAL 30
// CScrollBarCtl
IMPLEMENT_DYNAMIC(CScrollBarCtl, CWnd)
BEGIN_MESSAGE_MAP(CScrollBarCtl, CWnd)
ON_WM_PAINT()
ON_WM_SIZE()
ON_WM_MOUSEWHEEL()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDOWN()
ON_WM_VSCROLL()
ON_WM_KEYDOWN()
END_MESSAGE_MAP()
CScrollBarCtl::CScrollBarCtl()
{
m_nMaxPels=0; //滚动范围
m_nPagePels=0; //页面大小
m_nCurrentPos=0; //当前位置
m_nLineCount=0;
m_font.CreateFont(12, 0, 0, 0, 300,
FALSE, FALSE, 0,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH|FF_SWISS,
TEXT("宋体"));
}
CScrollBarCtl::~CScrollBarCtl()
{
}
void CScrollBarCtl::addText( CString str )
{
CRect rt;
if(!str.IsEmpty())
{
m_nLineCount++;
m_logisticsList.push_back(str);
GetClientRect(rt);
RectifyControl(rt.Width(), rt.Height());
}
}
//框架虚函数
BOOL CScrollBarCtl::PreTranslateMessage(MSG* pMsg)
{
//响应方向键
if (pMsg->message==WM_KEYDOWN)
{
switch (pMsg->wParam)
{
case VK_UP:
{
SendMessage(WM_VSCROLL,MAKELONG(SB_LINEUP,m_nCurrentPos),NULL);
return TRUE;
}
case VK_DOWN:
{
SendMessage(WM_VSCROLL,MAKELONG(SB_LINEDOWN,m_nCurrentPos),NULL);
return TRUE;
}
case VK_PRIOR:
{
SendMessage(WM_VSCROLL,MAKELONG(SB_PAGEUP,m_nCurrentPos),NULL);
return TRUE;
}
case VK_NEXT:
case VK_SPACE:
{
SendMessage(WM_VSCROLL,MAKELONG(SB_PAGEDOWN,m_nCurrentPos),NULL);
return TRUE;
}
case VK_HOME:
{
SendMessage(WM_VSCROLL,MAKELONG(SB_TOP,m_nCurrentPos),NULL);
return TRUE;
}
case VK_END:
{
SendMessage(WM_VSCROLL,MAKELONG(SB_BOTTOM,m_nCurrentPos),NULL);
return TRUE;
}
}
}
return CWnd::PreTranslateMessage(pMsg);
}
// CScrollBarCtl 消息处理程序
void CScrollBarCtl::OnPaint()
{
CPaintDC dc(this);
//使用涮缓冲避免闪烁
CRect rect;
GetClientRect(&rect);
m_nLineCount=0;
CDC MemDC;
CBitmap MemBitmap;
CTime tm = CTime::GetCurrentTime();
CString str;
str.Format(_T("%s %d:%d:%d"), tm.Format("%Y/%m/%d"), tm.GetHour(), tm.GetMinute(), tm.GetSecond());
MemDC.CreateCompatibleDC(NULL);
MemBitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
MemDC.SelectObject(&MemBitmap);
MemDC.FillSolidRect(0,0,rect.Width(),rect.Height(), RGB(230,230,230));
MemDC.SelectObject(&m_font);
MemDC.SetTextColor(RGB(50,50,50));
std::vector<CString>::iterator iter;
iter = m_logisticsList.begin();
INT nCurrentLine = 0;
TCHAR logisticsInfo[100];
for(;iter != m_logisticsList.end();iter++)
{
nCurrentLine++;
_tcscpy(logisticsInfo, (CString)(*iter));
MemDC.DrawText(logisticsInfo, CRect(CPoint(16, nCurrentLine*LINE_INTERVAL-m_nCurrentPos), CSize(500, 30)), DT_WORDBREAK|DT_BOTTOM|DT_VCENTER);
}
dc.BitBlt(0,0,rect.Width(),rect.Height(), &MemDC, 0, 0, SRCCOPY);
}
void CScrollBarCtl::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
RectifyControl(cx, cy);
}
BOOL CScrollBarCtl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
//zDelta滚轮的刻度,通常每旋转WHEEL_DELTA调用此函数一次
__super::OnMouseWheel(nFlags, zDelta, pt);
//设置变量
INT nLastPos=m_nCurrentPos;
m_nCurrentPos=__max(0,__min(m_nCurrentPos-zDelta/WHELL_PELS,m_nMaxPels-m_nPagePels));
//设置滚动
SetScrollPos(SB_VERT,m_nCurrentPos);
ScrollWindow(0,nLastPos-m_nCurrentPos,NULL,NULL);
return TRUE;
}
//滚动响应函数
void CScrollBarCtl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
__super::OnVScroll(nSBCode, nPos, pScrollBar);
INT nLastPos=m_nCurrentPos;
switch (nSBCode)
{
case SB_TOP: //滑到顶端
m_nCurrentPos=0;
break;
case SB_BOTTOM: //滑到低端
m_nCurrentPos=m_nMaxPels;
break;
case SB_LINEUP: //点击三角
m_nCurrentPos -= LINE_PELS;
break;
case SB_LINEDOWN: //点击三角
m_nCurrentPos += LINE_PELS;
break;
case SB_PAGEUP: //点击空白
{
m_nCurrentPos-=m_nPagePels;
}
break;
case SB_PAGEDOWN: //点击空白
{
m_nCurrentPos+=m_nPagePels;
}
break;
case SB_THUMBTRACK: //拖动滑块
m_nCurrentPos = nPos;
break;
}
//设置焦点
SetFocus();
//调整位置
m_nCurrentPos=__max(0,__min(m_nCurrentPos,m_nMaxPels-m_nPagePels));
//设置滚动
if (nLastPos!=m_nCurrentPos)
{
SetScrollPos(SB_VERT,m_nCurrentPos);
ScrollWindow(0,nLastPos-m_nCurrentPos,NULL,NULL);
}
return;
}
void CScrollBarCtl::RectifyControl( int cx, int cy )
{
m_nMaxPels = cy-1;
m_nPagePels=cy;
m_nCurrentPos=__max(0,__min(m_nCurrentPos,m_nMaxPels-m_nPagePels));
if(LINE_INTERVAL*(m_nLineCount + 1) > m_nMaxPels)
{
m_nMaxPels = LINE_INTERVAL*(m_nLineCount+1);
}
//设置滚动
SCROLLINFO ScrollInfo;
ScrollInfo.cbSize=sizeof(SCROLLINFO);
ScrollInfo.fMask=SIF_RANGE|SIF_PAGE|SIF_POS;
ScrollInfo.nMin=0;
ScrollInfo.nMax=m_nMaxPels;
ScrollInfo.nPage=m_nPagePels;
ScrollInfo.nPos=m_nCurrentPos;
SetScrollInfo(SB_VERT,&ScrollInfo,TRUE);
}
/////////////////////////////////////////////////////////////////
//3 使用方法
CRect rt;
GetClientRect(rt);
logis.Create (NULL,NULL,WS_TABSTOP | WS_CHILD| WS_VSCROLL ,CRect(0,0, rt.Width(), rt.Height()-100), this,12331);
for(WORD i=0; i < 20;i++)
{
logis.addText(_T("2015-04-09 20:55:52 已经签收"));
}
logis.ShowWindow(SW_SHOW);