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

okt*_*okt 3 winapi controls edit scrollbar

我有一个像这样创建的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
);
Run Code Online (Sandbox Code Playgroud)

如您所见,它是一个只读编辑区域,可以显示多行文本.它应该是一个控制台,我可以在用户使用该程序时显示一些信息.我希望每当添加新行(或用户的消息)时,文本区域会自动滚动到最底部的条目(最新的条目).我实现了这个:

 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 );
Run Code Online (Sandbox Code Playgroud)

在添加新的msg之后,该代码将垂直滚动条滚动到EDIT控件的末尾并且效果很好,滚动条滚动但文本仍然从头开始可见 - 它在添加后倒回到开头,而滚动条倒回到底部.如何使它正常?

最后但并非最不重要 - 这可能很重要 - 为了首先显示消息,我使用以下方法捕获已经显示的文本:GetDlgItemText(h2,ID_EDIT_CONSOLE,buf,len + 1); 然后我将buf转换为字符串并将该字符串添加到我要显示的新消息中.然后我将它转换回char数组并使用SetDlgItemText进行设置.我使用\ r \n分隔行.我这样编码是因为我不知道如何以不同于使用SetDlgItemText的方式向EDIT控件添加一行.并且它只添加一个条目AFAIK - 如果使用两次,我将不会将两个条目添加到EDIT控件中,但第一个将被第二个函数调用替换.

Ken*_*ite 6

不要使用SetScrollInfo.SendMessage()EM_LINESCROLL消息一起使用,将消息发送到编辑控件的窗口句柄.

SendMessage(MemoHwnd, EM_LINESCROLL, 0, NumLinesToScroll);
Run Code Online (Sandbox Code Playgroud)

文件说:

控件不会垂直滚动到编辑控件中的最后一行文本.如果当前行加上lParam参数指定的行数超过编辑控件中的行总数,则调整该值以使编辑控件的最后一行滚动到编辑控件窗口的顶部.


Blu*_*ire 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
Run Code Online (Sandbox Code Playgroud)

如果需要:要在编辑控件的末尾滚动而不附加文本:

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
Run Code Online (Sandbox Code Playgroud)


Jer*_*fin 5

您可以通过将所选内容的开头和结尾设置为控件中文本的末尾 ( EM_SETSEL ) 来添加文本,然后用新文本 ( EM_REPLACESEL )替换(空)所选内容。

在插入符号(选择内容)位于文本末尾后,可以使用EM_SCROLLCARET滚动到底部。还有其他方法,但如果您在添加文本后立即执行此操作,这可能是最简单的。