我有一个像这样创建的EDIT控件:
hwndEDIT_5 = CreateWindowEx (
0, "EDIT", NULL,
WS_VSCROLL | WS_BORDER | WS_VISIBLE | WS_CHILD | ES_MULTILINE | ES_READONLY,
135, 450, 555, 200,
h2, ( HMENU ) ID_EDIT_CONSOLE,
h1, NULL
);
如您所见,它是一个只读的编辑区域,可以显示多行文本。它应该是一个控制台,我可以在用户使用该程序时显示一些信息。我希望每当添加新行(或用户的消息)时,文本区域就会自动滚动到最底部的条目(最新的条目)。我实现了这个:
SetDlgItemText ( h2, ID_EDIT_CONSOLE, ch_s );
SCROLLINFO scr;
SCROLLINFO * scr_p = &scr;
scr.cbSize = sizeof ( SCROLLINFO );
scr.fMask = SIF_RANGE;
GetScrollInfo ( GetDlgItem ( h2, ID_EDIT_CONSOLE), SB_VERT, scr_p );
int mmax = scr.nMax;
scr.fMask = SIF_POS;
scr.nPos = mmax;
SetScrollInfo ( GetDlgItem ( h2, ID_EDIT_CONSOLE), SB_VERT, scr_p, TRUE );
该代码在添加新的msg之后将垂直滚动条滚动到EDIT控件的末尾并且效果很好,滚动条会滚动但文本仍然从头开始可见 - 它会在添加后重新开始,而滚动条会回滚到底部。如何正确使用?
最后但并非最不重要 - 这可能很重要 - 为了首先显示消息,我使用以下方法捕获已显示的文本: GetDlgItemText(h2,ID_EDIT_CONSOLE,buf,len + 1); 然后我将buf转换为字符串并将该字符串添加到我要显示的新消息中。然后我将它转换回char数组并使用SetDlgItemText进行设置。我使用\ r \ n分隔行。我这样编码是因为我不知道如何以不同于使用SetDlgItemText的方式向EDIT控件添加一行。并且它只添加一个条目AFAIK - 如果使用两次,我将不会将两个条目添加到EDIT控件中,但第一个将被第二个函数调用替换。
答案 0 :(得分:6)
不要使用SetScrollInfo。将SendMessage()
与EM_LINESCROLL消息一起使用,将消息发送到编辑控件的窗口句柄。
SendMessage(MemoHwnd, EM_LINESCROLL, 0, NumLinesToScroll);
文档说:
控件不会垂直滚动到编辑控件中的最后一行文本。如果当前行加上lParam参数指定的行数超过编辑控件中的行总数,则调整该值以使编辑控件的最后一行滚动到编辑控件窗口的顶部。
答案 1 :(得分:6)
我遇到了同样的问题,并用Jerry Coffin的答案和一些研究解决了这个问题。 这就是我现在使用的方式:
string text = "Append this text";
SendMessageA(hEdit, EM_SETSEL, 0, -1); //Select all
SendMessageA(hEdit, EM_SETSEL, -1, -1);//Unselect and stay at the end pos
SendMessageA(hEdit, EM_REPLACESEL, 0, (LPARAM)(text.c_str())); //append text to current pos and scroll down
如果需要:要在编辑控件的末尾滚动而不附加文本:
SendMessageA(hEdit, EM_SETSEL, 0, -1); //Select all.
SendMessageA(hEdit, EM_SETSEL, -1, -1);//Unselect and stay at the end pos
SendMessageA(hEdit, EM_SCROLLCARET, 0, 0); //Set scrollcaret to the current Pos
答案 2 :(得分:2)
您可以通过将所选内容的开头和结尾设置为控件(EM_SETSEL)中文本的末尾来添加文本,然后将(空)选择替换为新文本(EM_REPLACESEL )。
在插入符号(选择)位于文本末尾后,可以使用EM_SCROLLCARET滚动到底部。还有其他方法,但如果你在添加文本后立即这样做,这可能是最简单的。
答案 3 :(得分:0)
您可以使用的MFC项目:
mLoggingTextCtl.SendMessage(EM_SETSEL, 0, -1); //Select all.
mLoggingTextCtl.SendMessage(EM_SETSEL, -1, -1);//Unselect and stay at the end pos
mLoggingTextCtl.SendMessage(EM_SCROLLCARET, 0, 0); //Set scrollcaret to the current Pos
答案 4 :(得分:0)
在我的情况下,我有多行字符串,而Ken White的想法非常有效:
HWND hEdit = this->GetDlgItem(IDC_EDIT_LOG)->m_hWnd;
if (hEdit)
{
int lineCount = m_strClientLog.Replace(_T("\n"), _T("\n"));
::SendMessage(hEdit, EM_LINESCROLL, 0, lineCount);
}