修改
感谢@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.如何检测到滚动条已滚动到底部?
答案 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 == 0
和nPage == 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,我们只需退出,无需额外滚动