我整理了一下,大家一看就明白怎么回事。滚动条实际很简单,给那些没功夫自己查找的人提供方便,也算是有点贡献。
从下面可知,可以分解为3部分。
声明和创建滚动条对象
设置滚动条大小和位置
设置滚动条滑块的位置,更具滑块位置设置其他对象状态
// TestdvView.h : interface of the CTestdvView class
//
/
#if !defined(AFX_TESTDVVIEW_H__9E125D98_F709_4D10_9376_763413E3F0CA__INCLUDED_)
#define AFX_TESTDVVIEW_H__9E125D98_F709_4D10_9376_763413E3F0CA__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CTestdvView : public CView
{
protected: // create from serialization only
CTestdvView();
DECLARE_DYNCREATE(CTestdvView)
// Attributes
public:
CTestdvDoc* GetDocument();
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTestdvView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CTestdvView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CTestdvView)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
CScrollBar m_wndSBHorz;
INT CalcScrollOffset(CScrollBar* pwndSB, INT nCode, UINT nPos, int nScrollHeight,int nScrollPageHeight);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnSize(UINT nType, int cx, int cy);
};
#ifndef _DEBUG // debug version in TestdvView.cpp
inline CTestdvDoc* CTestdvView::GetDocument()
{ return (CTestdvDoc*)m_pDocument; }
#endif
/
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_TESTDVVIEW_H__9E125D98_F709_4D10_9376_763413E3F0CA__INCLUDED_)
// TestdvView.cpp : implementation of the CTestdvView class
//
#include "stdafx.h"
#include "Testdv.h"
#include "TestdvDoc.h"
#include "TestdvView.h"
#include "./testdvview.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CTestdvView
IMPLEMENT_DYNCREATE(CTestdvView, CView)
BEGIN_MESSAGE_MAP(CTestdvView, CView)
//{{AFX_MSG_MAP(CTestdvView)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
ON_WM_CREATE()
ON_WM_HSCROLL()
ON_WM_SIZE()
END_MESSAGE_MAP()
/
// CTestdvView construction/destruction
CTestdvView::CTestdvView()
{
// TODO: add construction code here
}
CTestdvView::~CTestdvView()
{
}
BOOL CTestdvView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/
// CTestdvView drawing
void CTestdvView::OnDraw(CDC* pDC)
{
CTestdvDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
/
// CTestdvView diagnostics
#ifdef _DEBUG
void CTestdvView::AssertValid() const
{
CView::AssertValid();
}
void CTestdvView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CTestdvDoc* CTestdvView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestdvDoc)));
return (CTestdvDoc*)m_pDocument;
}
#endif //_DEBUG
/
// CTestdvView message handlers
int CTestdvView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您专用的创建代码
VERIFY(m_wndSBHorz.Create(WS_VISIBLE|WS_CHILD|SBS_HORZ,CRect(0,0,0,0), this,1));
return 0;
}
void CTestdvView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// ignore scroll bar msgs from other controls
if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg())
return; // eat it
//CScrollBar* ptemScrollBar= GetScrollBarCtrl(SB_HORZ);//ptemScrollBar总是NULL因为它不是view自带的
//if (pScrollBar != ptemScrollBar) return;
OnScroll(MAKEWORD(nSBCode,-1), nPos);
int Min = 0, Max = 0;
pScrollBar->GetScrollRange( &Min, &Max);
int nScrollHeight = Max/10+1;//滚动一下的高度
int nScrollPageHeight = nScrollHeight*2;//滚动一页的高度
INT Offset = CalcScrollOffset(pScrollBar, LOBYTE(nSBCode), nPos, nScrollHeight, nScrollPageHeight);
// adjust current x position
int OldPos = 0;
int NewPos = 0;
OldPos = NewPos = pScrollBar->GetScrollPos();//
NewPos += Offset;
if (NewPos < 0)NewPos = 0;
else if (NewPos > Max)NewPos = Max;
// did anything change?
if (NewPos != OldPos)
{
pScrollBar->SetScrollPos(NewPos);
//编写其他的对应代码。
}
CView::OnHScroll(nSBCode, nPos, pScrollBar);
}
INT CTestdvView::CalcScrollOffset(CScrollBar* pwndSB, INT nCode, UINT nPos, int nScrollHeight,int nScrollPageHeight)
{
// calc new position
INT nOldPos;
nOldPos = pwndSB->GetScrollPos();
INT nNewPos = nOldPos;
switch(nCode)
{
case SB_TOP:
nNewPos = 0;
break;
case SB_BOTTOM:
nNewPos = INT_MAX;
break;
case SB_LINEUP:
nNewPos -= nScrollHeight;
break;
case SB_LINEDOWN:
nNewPos += nScrollHeight;
break;
case SB_PAGEUP:
nNewPos -= nScrollPageHeight;
break;
case SB_PAGEDOWN:
nNewPos += nScrollPageHeight;
break;
case SB_THUMBPOSITION:
nNewPos = ((nPos+nScrollHeight/2)/nScrollHeight)*nScrollHeight;
break;
case SB_THUMBTRACK:
nNewPos = ((nPos+nScrollHeight/2)/nScrollHeight)*nScrollHeight;
break;
}
return nNewPos - nOldPos;
}
void CTestdvView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
CRect rtWindow(0, 0, 0, 0);
::GetWindowRect(this->GetSafeHwnd(),&rtWindow);
m_wndSBHorz.MoveWindow(0,rtWindow.Height()-20,rtWindow.Width(),17,TRUE);
//m_wndSBHorz.ShowWindow(SW_HIDE);
SCROLLINFO ScrollInfo;
ScrollInfo.cbSize = sizeof(SCROLLINFO);
ScrollInfo.fMask = SIF_ALL;
//m_wndSBHorz.SetScrollRange(0, rtWindow.Width(), FALSE);
ScrollInfo.nMax = rtWindow.Width();//滚动条最大滚动值
ScrollInfo.nMin = 0;//滚动条最小滚动值
//m_wndSBHorz.SetScrollPos(100);
ScrollInfo.nPos = 50;//滚动条的位置
ScrollInfo.nPage = 100;
m_wndSBHorz.SetScrollInfo(&ScrollInfo,TRUE);//m_ScrollBar为自己的滚动条
if(!m_wndSBHorz.IsWindowVisible())m_wndSBHorz.ShowWindow(SW_SHOW);//放在后面是为了避免闪动
}