vc++ 添加可以滚动整个窗口的滚动条(水平和竖直)并可使用鼠标滚动轮和键盘上的上下键控制滚动条

来源:互联网 发布:环北京贫困带 知乎 编辑:程序博客网 时间:2024/04/30 07:44

水平和竖直的滚动条可以在窗口的属性中添加,分别是:Horizontal scroll和Vertical scroll。

一.竖直滚动条

1.初始化

void CScroolDlgDlg::InitScrool()
{
CRect rtClient;
GetClientRect(rtClient);
SCROLLINFO vInfo;
vInfo.cbSize = sizeof(SCROLLINFO);
vInfo.fMask = SIF_ALL;
vInfo.nMax = 600;//这是你要滚动的范围
vInfo.nMin = vInfo.nPos = vInfo.nTrackPos = 0; //这个为0即可
vInfo.nPage = rtClient.bottom;//这是你窗口的高度(横向滚动条的话就是窗口的宽度)
SetScrollInfo(SB_VERT, &vInfo);//(SB_HORT就设置横向滚动条)
}

2.添加WM_VSCROLL事件

void CScroolDlgDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
// TODO: Add your message handler code here and/or call default
SCROLLINFO vinfo = {0};
GetScrollInfo(SB_VERT, &vinfo, SIF_ALL);
int iPos = vinfo.nPos;


INT32 iMaxPos = vinfo.nMax-vinfo.nPage;

int hPage = vinfo.nPage;
int Inc = 1;


switch (nSBCode)
{
case SB_BOTTOM://滚动到最下面
if (vinfo.nPos < iMaxPos)
{
ScrollWindow(0, -1*Inc * (iMaxPos-vinfo.nPos));
vinfo.nPos = iMaxPos;
}
break;


case SB_TOP: //滚动到最上面
if (vinfo.nPos > vinfo.nMin)
{
ScrollWindow(0, Inc * (vinfo.nPos-vinfo.nMin));
vinfo.nPos = vinfo.nMin;
}
break;


case SB_LINEUP://向上滚动一行
if (vinfo.nPos > vinfo.nMin)
{
ScrollWindow(0, Inc);
vinfo.nPos -= 1;
}
break;


case SB_LINEDOWN://向下滚动一行
if (vinfo.nPos < iMaxPos)
{
ScrollWindow(0, -1*Inc);
vinfo.nPos += 1;
}
break;


case SB_PAGEUP: //向上滚动一页
if (vinfo.nPos-100 >= vinfo.nMin)
{
ScrollWindow(0, 100*Inc);
vinfo.nPos -= 100;
}
else
{
// ScrollWindow(0, (vinfo.nPos-iMaxPos)*Inc);
if (vinfo.nPos <= 0)
{
ScrollWindow(0,0);
}
else
{
ScrollWindow(0,vinfo.nPos);
}
// ScrollWindow(0, max(0,(vinfo.nPos-iMaxPos)*Inc));
vinfo.nPos = vinfo.nMin;
}
break;


case SB_PAGEDOWN: //向下滚动一页
if (vinfo.nPos+100 <= iMaxPos)
{
ScrollWindow(0, -100*Inc);
vinfo.nPos += 100;
}
else
{
ScrollWindow(0, (vinfo.nPos-iMaxPos)*Inc);
vinfo.nPos = iMaxPos;
}
break;


case SB_ENDSCROLL://滚动条移动结束
break;


case SB_THUMBPOSITION:
break;


case SB_THUMBTRACK:
ScrollWindow(0, Inc * (vinfo.nPos - nPos));
vinfo.nPos = nPos;
break;
}
SetScrollInfo(SB_VERT, &vinfo);


CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}


二、水平滚动条

1.初始化

void CScroolDlgDlg::InitBottomScroll()
{
CRect rtClient;
GetClientRect(rtClient);
SCROLLINFO hInfo;
hInfo.cbSize = sizeof(SCROLLINFO);
hInfo.fMask = SIF_ALL;
hInfo.nMax = 1000;//这是你要滚动的范围
hInfo.nMin = hInfo.nPos = hInfo.nTrackPos = 0; //这个为0即可
hInfo.nPage = rtClient.Width();//这是窗口的宽度(如果是横向滚动条的话,就这是你窗口的高度)
SetScrollInfo(SB_HORZ, &hInfo);//(SB_VERT就设置纵向滚动条)

}

2.添加WM_HSCROLL事件

void CMySpaceSubmitInfo::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
// TODO: Add your message handler code here and/or call default
SCROLLINFO hInfo = {0};
GetScrollInfo(SB_HORZ,&hInfo,SIF_ALL);
int iMaxPos = hInfo.nMax - hInfo.nPage;
int hPage = hInfo.nPage;
int inc = 1;
  // Determine the new position of scroll box.
  switch (nSBCode)
  {
  case SB_LEFT:      // Scroll to far left.
  ScrollWindow(inc *(hInfo.nPos-hInfo.nMin),0);
  hInfo.nPos = hInfo.nMin;
  break;
  
  case SB_RIGHT:      // Scroll to far right.
  ScrollWindow(-1*inc*(iMaxPos - hInfo.nPos),0);
  hInfo.nPos = iMaxPos;
  break;
  
  case SB_ENDSCROLL:   // End scroll.
  break;
  
  case SB_LINELEFT:      // Scroll left.
  if (hInfo.nPos > hInfo.nMin)
  {
  ScrollWindow(inc,0);
  hInfo.nPos -=1;
  }
  break;
  
  case SB_LINERIGHT:   // Scroll right.
  if(hInfo.nPos <=iMaxPos)
  {
  ScrollWindow(-1*inc,0);
  hInfo.nPos +=1;
  }
  break;
  
  case SB_PAGELEFT:    // Scroll one page left.
  {
  // Get the page size.   
  if (hInfo.nPos - 100 >= hInfo.nMin)
  {
  ScrollWindow(100*inc,0);
  hInfo.nPos -=100;
  }
  else
  {
  if (hInfo.nPos <= 0)
  {
  ScrollWindow(0,0);
  }
  else
  {
  ScrollWindow(hInfo.nPos,0);
  }
//   ScrollWindow((hInfo.nPos - iMaxPos)*inc,0);
  hInfo.nPos = hInfo.nMin;
  }
  }
  break;
  
  case SB_PAGERIGHT:      // Scroll one page right.
  {
  // Get the page size.   
  if (hInfo.nPos + 100 <= iMaxPos)
  {
  ScrollWindow(-100*inc,0);
  hInfo.nPos +=100;
  }
  else
  {
  ScrollWindow((hInfo.nPos - iMaxPos)*inc,0);
  hInfo.nPos = iMaxPos;
  }
  }
  break;
  
  case SB_THUMBPOSITION: // Scroll to absolute position. nPos is the position
  //   curpos = nPos;      // of the scroll box at the end of the drag operation.
  break;
  
  case SB_THUMBTRACK:   // Drag scroll box to specified position. nPos is the
  ScrollWindow(inc*(hInfo.nPos-nPos),0);
  hInfo.nPos = nPos;     // position that the scroll box has been dragged to.
  break;
  }
  
  // Set the new position of the thumb (scroll box).
 SetScrollInfo(SB_HORZ,&hInfo);
CDialog::OnHScroll(nSBCode, nPos, pScrollBar);

}


三、使用鼠标滑动轮来滑动竖直窗口滚动条

1.添加事件:ON_WM_MOUSEWHEEL

2.代码:

BOOL CScroolDlgDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
{
// TODO: Add your message handler code here and/or call default
SCROLLINFO vinfo = {0};
GetScrollInfo(SB_VERT, &vinfo, SIF_ALL);
int iPos = vinfo.nPos;
INT32 iMaxPos = vinfo.nMax-vinfo.nPage;
//首先判断鼠标滚动的方向/////////////////////////
//1.如果鼠标滚动条向上(远离使用者),此时zDelta的值为正.
//判断滚动条是否已经到了上顶了
if (zDelta > 0)
{
if (iPos <= 0)
{
;
}
else
{
int iScrollUp = iPos - zDelta;
if (iScrollUp < 0)
{
ScrollWindow(0,iPos);
vinfo.nPos = vinfo.nMin;
}
else
{
ScrollWindow(0,zDelta);
vinfo.nPos -= zDelta;
}
}
}
else if (zDelta < 0) //向下滑动鼠标滚动轮
{
if (iPos >= iMaxPos)
{
;
}
else
{
int iScrollDown = iPos + (-1)*zDelta;
if (iScrollDown > iMaxPos) 
{
ScrollWindow(0,iPos-iMaxPos);
vinfo.nPos = iMaxPos;
}
else
{
ScrollWindow(0,zDelta);
vinfo.nPos = vinfo.nPos + (-1)*zDelta;
}
}
}
SetScrollInfo(SB_VERT,&vinfo);
return CDialog::OnMouseWheel(nFlags, zDelta, pt);
}


四、使用键盘上的上下箭头进行滑动窗口滚动条

1.添加消息:PreTranslateMessage

2.代码:

BOOL CScroolDlgDlg::PreTranslateMessage(MSG* pMsg) 
{
// TODO: Add your specialized code here and/or call the base class
if (pMsg->message == WM_KEYDOWN)
{
if (pMsg->wParam == VK_DOWN)
{
int iScroNum = 5;
SCROLLINFO vInfo = {0};
GetScrollInfo(SB_VERT,&vInfo,SIF_ALL);
int iPos = vInfo.nPos;
INT32 iMax = vInfo.nMax - vInfo.nPage;
//首先判断窗口滚动条是否已经到了最下面
if (iPos >= iMax)
{
;
}
else
{
//判断向下滑动5像素后是否会超过向下滑动的最大值
int iScrolDown = iScroNum + iPos;
if (iScroNum > iMax) //超过了
{
ScrollWindow(0,iPos - iMax);
vInfo.nPos = iMax;
}
else if (iScrolDown <= iMax) //移动后不超过最下面
{
ScrollWindow(0,(-1)*iScroNum);
vInfo.nPos += iScroNum;
}
}
SetScrollInfo(SB_VERT,&vInfo);
}//end down

if (pMsg->wParam == VK_UP)
{
SCROLLINFO vInfo = {0};
GetScrollInfo(SB_VERT,&vInfo,SIF_ALL);
int iPos = vInfo.nPos;
UINT32 iMaxPos = vInfo.nMax - vInfo.nPage;
int iScroNum= 5;//移动的
//首先判断是否已经到了最顶部
if (iPos <= 0)
{
;
}
else
{
//判断当滚动后是否超出顶部
int iScrollUp = iPos - iScroNum;
if (iScrollUp < 0) //超出了
{
ScrollWindow(0,iPos);
vInfo.nPos = vInfo.nMin;
}
else if (iScrollUp >= 0)
{
ScrollWindow(0,iScroNum);
vInfo.nPos -= iScroNum;
}
}
SetScrollInfo(SB_VERT,&vInfo);
}//end up
}
return CDialog::PreTranslateMessage(pMsg);
}

附:水平有限,如有其他好的建议请各位同修提出。

0 0