继承cwnd的滚动条控件

本文档介绍了如何创建一个继承自CWnd的CScrollBarCtl类,该类实现了自定义滚动条控件,支持添加文本、响应鼠标滚轮、键盘方向键等操作,用于显示和滚动物流信息列表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//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);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值