mfc新建空项目,写了一个滚动条,只能往下滚,往上滚出现bug,出错原因,还有怎么改?

头文件

#include<afxwin.h>

class Cmyapp :public  CWinApp
{

public:
    virtual BOOL InitInstance();
};

class Cmywindow :public CFrameWnd
{
public:
    Cmywindow();

    DECLARE_MESSAGE_MAP()
    afx_msg void OnPaint();

protected:
    int pagesize;        //页面大小
    int fullsize;        //整个数据窗口大小
    int slied;           //滑块位置
public:
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
};

cpp文件

#include "scroll.h"

#define linemax 100
#define linesize 50
bool is = 0;
Cmyapp app;

BOOL Cmyapp::InitInstance()
{
    // TODO: 在此添加专用代码和/或调用基类
    this->m_pMainWnd = new Cmywindow();
    this->m_pMainWnd->ShowWindow(m_nCmdShow);
    this->m_pMainWnd->UpdateWindow();

    return CWinApp::InitInstance();
}

Cmywindow::Cmywindow()
{
    this->Create(NULL, TEXT("scroll"), WS_OVERLAPPEDWINDOW|WS_VSCROLL);
}

BEGIN_MESSAGE_MAP(Cmywindow, CFrameWnd)
    ON_WM_PAINT()
    ON_WM_CREATE()
    ON_WM_SIZE()
    ON_WM_VSCROLL()
END_MESSAGE_MAP()


void Cmywindow::OnPaint()
{
    CPaintDC dc(this); // device context for painting
                       // TODO: 在此处添加消息处理程序代码
                       // 不为绘图消息调用 CFrameWnd::OnPaint()
    dc.SetWindowOrg(0,slied);                         //设立原点

    CFont cfont;                                      //建立字体
    cfont.CreatePointFont(120,TEXT("Arial"));      
    dc.SelectObject(&cfont);                          //载入字体



    for (int i = 0,a=0; i < linemax; i++,a++)         //打印hello mfc和数字
    {
        CString b;
        b.Format(TEXT("%d"), a);
        dc.TextOutW(0, i*linesize, TEXT("HELLO MFC"), 9);
        dc.TextOutW(240, i*linesize, b);
    }

}


int Cmywindow::OnCreate(LPCREATESTRUCT lpCreateStruct)   //窗口创建时,对滑块和整个数据窗口大小赋值
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  在此添加您专用的创建代码

    slied = 0;
    fullsize = linesize * linemax;

    return 0;
}


void Cmywindow::OnSize(UINT nType, int cx, int cy)       //窗口大小改变时
{
    CFrameWnd::OnSize(nType, cx, cy);

    pagesize = cy;                                       //将现有窗口y轴大小赋值给页面大小

    SCROLLINFO myvacroll;                                //定义SCROLLINFO结构
    myvacroll.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;    //滚动条用到的参数
    myvacroll.nMin = 0;                                  //滚动条最小值
    myvacroll.nMax = fullsize;                           //滚动条最大值
    myvacroll.nPage = cy;                                //滚动条页面大小
    myvacroll.nPos = slied;                              //滚动条滑块位置

    this->SetScrollInfo(SB_VERT,&myvacroll,TRUE);        //重新设置滚动条参数

    // TODO: 在此处添加消息处理程序代码
}


void Cmywindow::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)   //竖立滚动条参数
{
    //int nDelta = 0;                                       //页面改变参数
    //switch (nSBCode)
    //{
    //case SB_LINEUP:                                       //向上滚动一行,就是按向上的箭头
    //  nDelta = -linesize;                                 //页面向下移动一行
    //  break;
    //case SB_PAGEUP:                                       //向上滚动一页
    //  nDelta = -pagesize;                                 //页面向下移动一页
    //  break;
    //case SB_THUMBTRACK:                                   //拖动到指定位置
    //  nDelta = nPos - slied;                              //
    //  break;
    //case SB_PAGEDOWN:                                     //向下滚动一页
    //  nDelta = pagesize;                                  //页面向上一页
    //  break;
    //case SB_LINEDOWN:                                     //向下滚动一行
    //  nDelta = linesize;                                  //页面向上一行
    //  break;
    //default:
    //  break;
    //}

    //if (nDelta != 0)                                      //如果页面不需要改动,就不执行
    //{
    //  slied += nDelta;                                    //将滑动块位置移动到正确的位置   
    //  SetScrollPos(SB_VERT, slied, TRUE);
    //  ScrollWindow(0, -nDelta);
    //}


    switch (nSBCode)
    {

    case SB_LINEDOWN:            //向下一行
        slied += linesize;
        break;
    case SB_LINEUP:              //向上一行
        slied -= linesize;
        break;
    case SB_PAGEDOWN:            //向下一页
        slied += pagesize;
        break;
    case SB_PAGEUP:              //向上一页
        slied -= pagesize;
        break;
    case SB_THUMBTRACK:          //滚动条移动后,鼠标左键松掉
        slied = nPos;
        break;
    default:
        break;
    }

    SetScrollPos(SB_VERT, slied,TRUE);                      //设定滑块位置
    ScrollWindow(0, -(slied - (int)nPos));                  //设定滑动后绘图框的内容跟着移动

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

cpp文件最后的OnVScroll消息中,如果用被注释掉的代码,滚动条就是对的,如果用没注释掉的,滚动条就是错的!

1个回答

ScrollWindow(0, -nDelta);
应该是这里,你在OnVScroll里调用ScrollWindow,它又会触发新的VScroll,导致无限递归了。

weixin_44826062
moon19961996 应该是ScrollWindow参数2需要接受滚动条移动差值,来移动绘图区,如果不优先建立一个差值,就需要对各种情况分开建立差值,所以注释掉的写法才是最简的
10 个月之前 回复
weixin_44826062
moon19961996 如果用被注释掉的代码,滚动条就是对的,如果用没注释掉的,滚动条就是错的!
10 个月之前 回复
weixin_44826062
moon19961996 这不是一样的吗,注释的代码里也调用ScrollWindow了啊
10 个月之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问