Win32 API:如何在EDIT控件内自动向下滚动文本?

时间:2012-02-20 02:59:54

标签: winapi controls scrollbar edit

我有一个像这样创建的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控件中,但第一个将被第二个函数调用替换。

5 个答案:

答案 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); }