MFC滚动条如何正确使用

MFC对话框中有一些按钮和列表,想要做一个垂直滚动条使得当对话框较小,里面内容显示不全时,能通过滚动条显示。
现在遇到的问题是,滚动条滚动至最下方,按理来说对话框也应该显示到最下方的内容,但是会多显示一部分空白,这是为什么啊?
目前用的是对话框的垂直滚动条属性,没用垂直滚动条控件

img

void CUIDialog::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    SCROLLINFO scrollinfo;
    GetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
    int unit = 3;
    switch (nSBCode)
    {
    case SB_LINEUP:          //滚动一行
        scrollinfo.nPos -= 1;
        if (scrollinfo.nPos < scrollinfo.nMin)
        {
            scrollinfo.nPos = scrollinfo.nMin;
            break;
        }
        SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
        ScrollWindow(0, unit);
        break;
    case SB_LINEDOWN:           //向下滚动一行
        scrollinfo.nPos += 1;
        if (scrollinfo.nPos + scrollinfo.nPage > scrollinfo.nMax)  //此处要加上滑块的长度,再作判断
        {
            scrollinfo.nPos = scrollinfo.nMax;
            break;
        }
        SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
        ScrollWindow(0, -unit);
        break;
    case SB_PAGEUP:            //滚动一页
        scrollinfo.nPos -= 5;
        if (scrollinfo.nPos <= scrollinfo.nMin)
        {
            scrollinfo.nPos = scrollinfo.nMin;
            break;
        }
        SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
        ScrollWindow(0, unit * 5);
        break;
    case SB_PAGEDOWN:        //向下滚动一页        
        scrollinfo.nPos += 5;
        if (scrollinfo.nPos + scrollinfo.nPage >= scrollinfo.nMax)  //此处要加上滑块的长度,再作判断
        {
            scrollinfo.nPos = scrollinfo.nMax;
            break;
        }
        SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
        ScrollWindow(0, -unit * 5);
        break;
    case SB_ENDSCROLL:
        break;
    case SB_THUMBPOSITION:
        break;
    case SB_THUMBTRACK:        //将滚动条拖动到指定位置       
        ScrollWindow(0, (scrollinfo.nPos - nPos) * 10);
        scrollinfo.nPos = nPos;
        SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
        break;
    }
    CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}

可能是由于滚动条的范围和页面范围的设置问题导致的
你可以参考试试这样设置

CRect rectClient;
GetClientRect(&rectClient);

CRect rectWindow;
GetWindowRect(&rectWindow);

int nWidth = rectClient.Width();
int nHeight = rectClient.Height();

int nScrollHeight = rectWindow.Height() - nHeight;
int nPageHeight = nHeight;

m_scrollBarVert.SetScrollRange(0, nScrollHeight);
m_scrollBarVert.SetScrollPage(nPageHeight);

m_scrollBarVert是垂直滚动条控件的成员变量。通过计算对话框控件的大小和位置,以及滚动条的范围和页面范围,我们确保滚动条可以滚动到对话框的最底部,而不会出现空白部分。

对话框的代码也发出来,看一下你要以什么作为滚动条的范围,你现在的代码未正确设置滚动范围,导致你的界面滚动几下就会乱掉。

可以借鉴下

void CceshiDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
  // TODO: 在此添加消息处理程序代码和/或调用默认值
​
  CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
  SCROLLINFO scrollinfo;
  GetScrollInfo(SB_HORZ, &scrollinfo, SIF_ALL);
  //
  switch (nSBCode)
  {
  case SB_LEFT:
    ScrollWindow((scrollinfo.nPos - scrollinfo.nMin) * 10, 0);
    scrollinfo.nPos = scrollinfo.nMin;
    SetScrollInfo(SB_HORZ, &scrollinfo, SIF_ALL);
    break;
  case SB_RIGHT:
    ScrollWindow((scrollinfo.nPos - scrollinfo.nMax) * 10, 0);
    scrollinfo.nPos = scrollinfo.nMax;
    SetScrollInfo(SB_HORZ, &scrollinfo, SIF_ALL);
    break;
  case SB_LINELEFT:
    scrollinfo.nPos -= 1;
    if (scrollinfo.nPos < scrollinfo.nMin)
    {
      scrollinfo.nPos = scrollinfo.nMin;
      break;
    }
    SetScrollInfo(SB_HORZ, &scrollinfo, SIF_ALL);
    ScrollWindow(10, 0);
    break;
  case SB_LINERIGHT:
    scrollinfo.nPos += 1;
    if (scrollinfo.nPos > scrollinfo.nMax)
    {
      scrollinfo.nPos = scrollinfo.nMax;
      break;
    }
    SetScrollInfo(SB_HORZ, &scrollinfo, SIF_ALL);
    ScrollWindow(-10, 0);
    break;
  case SB_PAGELEFT:
    scrollinfo.nPos -= 5;
    if (scrollinfo.nPos < scrollinfo.nMin)
    {
      scrollinfo.nPos = scrollinfo.nMin;
      break;
    }
    SetScrollInfo(SB_HORZ, &scrollinfo, SIF_ALL);
    ScrollWindow(10 * 5, 0);
    break;
  case SB_PAGERIGHT:
    scrollinfo.nPos += 5;
    if (scrollinfo.nPos > scrollinfo.nMax)
    {
      scrollinfo.nPos = scrollinfo.nMax;
      break;
    }
    SetScrollInfo(SB_HORZ, &scrollinfo, SIF_ALL);
    ScrollWindow(-10 * 5, 0);
    break;
  case SB_THUMBPOSITION:
    break;
  case SB_THUMBTRACK:
    ScrollWindow((scrollinfo.nPos - nPos) * 10, 0);
    scrollinfo.nPos = nPos;
    SetScrollInfo(SB_HORZ, &scrollinfo, SIF_ALL);
    break;
  case SB_ENDSCROLL:
    break;
  }
}
​
​
void CceshiDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
  // TODO: 在此添加消息处理程序代码和/或调用默认值
​
  CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
  SCROLLINFO scrollinfo;
  GetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
  switch (nSBCode)
  {
  case SB_LINEUP:          //Scroll one line up
    scrollinfo.nPos -= 1;
    if (scrollinfo.nPos < scrollinfo.nMin)
    {
      scrollinfo.nPos = scrollinfo.nMin;
      break;
    }
    SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
    ScrollWindow(0, 10);
    break;
  case SB_LINEDOWN:           //Scroll one line down
    scrollinfo.nPos += 1;
    if (scrollinfo.nPos + scrollinfo.nPage > scrollinfo.nMax)  //此处一定要注意加上滑块的长度,再作判断
    {
      scrollinfo.nPos = scrollinfo.nMax;
      break;
    }
    SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
    ScrollWindow(0, -10);
    break;
  case SB_PAGEUP:            //Scroll one page up.
    scrollinfo.nPos -= 5;
    if (scrollinfo.nPos <= scrollinfo.nMin)
    {
      scrollinfo.nPos = scrollinfo.nMin;
      break;
    }
    SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
    ScrollWindow(0, 10 * 5);
    break;
  case SB_PAGEDOWN:        //Scroll one page down        
    scrollinfo.nPos += 5;
    if (scrollinfo.nPos + scrollinfo.nPage >= scrollinfo.nMax)  //此处一定要注意加上滑块的长度,再作判断
    {
      scrollinfo.nPos = scrollinfo.nMax;
      break;
    }
    SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
    ScrollWindow(0, -10 * 5);
    break;
  case SB_ENDSCROLL:      //End scroll     
    break;
  case SB_THUMBPOSITION:  //Scroll to the absolute position. The current position is provided in nPos
    break;
  case SB_THUMBTRACK:                  //Drag scroll box to specified position. The current position is provided in nPos
    ScrollWindow(0, (scrollinfo.nPos - nPos) * 10);
    scrollinfo.nPos = nPos;
    SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
    break;
  }
}
​

首先检查对话框最下方是否有设置边距,距离等属性,从而导致距离底部有空白。其次有可能是对话框自带滚动条默认的样式设置,预留的空白,可以更换为滚动条组件之后看该空白是否还会出现。

因为计算垂直滚动条滚动位置时没有考虑对话框顶部的边框或内边距。导致滚动到底部后,对话框内容并没有滚动到底部,而是留有一部分空白。