如何检查编辑控件的滚动条是否在底部?

时间:2016-12-08 23:46:01

标签: c++ winapi scrollbar

修改

感谢@immibis,我现在可以使用WM_VSCROLL成功滚动到控件的底部,但我仍然想知道如何检查滚动条是否位于底部。

我有一个只读编辑控件:

HWND hMsgDisplay = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", NULL, WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_READONLY | WS_VSCROLL, 10, 10, 664, 200, hWnd, (HMENU)IDC_MESSAGE_DISPLAY_EDIT, hInst, NULL);

我想滚动到它的底部。我一直在尝试这个:

SCROLLINFO sb;
ZeroMemory(&sb, sizeof(sb));
sb.cbSize = sizeof(SCROLLBARINFO);
sb.fMask = SIF_ALL;
GetScrollInfo(hMsgDisplay, SB_VERT, &sb);
while (abs(sb.nMax - sb.nPos) > 1) {
    SendMessage(hMsgDisplay, EM_SCROLL, SB_LINEDOWN, NULL);
    GetScrollInfo(hMsgDisplay, SB_VERT, &sb);
}

当编辑控件中只有一行或两行文本时,它工作正常,但之后程序进入无限循环并卡住。我调试了它,发现即使滚动条是灰色的(它在那里但它不能滚动),sb.nMax仍然给我一个非零数字,无论我发送多少次{{1消息,EM_SCROLL仍为0.如何检测到滚动条已滚动到底部?

1 个答案:

答案 0 :(得分:2)

检查底部位置使用此代码

BOOL IsBotomPos(HWND hwnd)
{
    SCROLLINFO si = {sizeof(si), SIF_ALL};

    if (GetScrollInfo(hwnd, SB_VERT, &si))
    {
        return si.nPos + si.nPage == (UINT)si.nMax + 1;
    }

    return -1;
}

因此条件为si.nPos + si.nPage == (UINT)si.nMax + 1;

这也是返回true进行空编辑或滚动尚未激活(在这种情况下为nPos == 0nPage == nMax + 1

滚动到底部你可以简单地调用

SendMessage(hwnd, EM_SCROLL, SB_BOTTOM, 0);

尽管SB_BOTTOM使用EM_SCROLL未记录,但它可以在我的测试中使用

如果你想要平滑滚动 - 你可以使用下一个代码:

void DoSmoothScroll(HWND hwnd, BOOL byPage)
{
    SCROLLINFO si = {sizeof(si), SIF_ALL};

    if (GetScrollInfo(hwnd, SB_VERT, &si))
    {
        int n = si.nMax + 1 - si.nPage - si.nPos;

        if (0 < n)
        {
            if (byPage && si.nPage)
            {
                n = (n + si.nPage - 1) / si.nPage;
                LONG r = MAKELONG(si.nPage - 1, TRUE);
                do 
                {
                    if (SendMessage(hwnd, EM_SCROLL, SB_PAGEDOWN, 0) != r)
                    {
                        break;
                    }
                } while (--n);
            }
            else
            {
                do 
                {
                    if (SendMessage(hwnd, EM_SCROLL, SB_LINEDOWN, 0) != MAKELONG(1, TRUE))
                    {
                        break;
                    }
                } while (--n);
            }
        }
    }
}

你也可以结合 - 首先尝试快速滚动&#34;未记录&#34; SB_BOTTOM,然后检查我们是否真的滚动,如果没有 - 尝试平滑滚动

void ScrollEx(HWND hwnd)
{
    SendMessage(hwnd, EM_SCROLL, SB_BOTTOM, 0);
    DoSmoothScroll(hwnd, TRUE);
}

真正在函数DoSmoothScroll

int n = si.nMax + 1 - si.nPage - si.nPos;

如果SB_BOTTOM有效,

必须为0,我们只需退出,无需额外滚动