Win32 API: Как автоматически прокрутить текст вниз внутри элемента управления EDIT? - PullRequest
3 голосов
/ 20 февраля 2012

У меня есть элемент управления 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
);

Как вы можете видеть, это область редактирования EDIT только для чтения, в которой может отображаться многострочный текст.Предполагается, что это будет консоль, где я могу отображать некоторую информацию для пользователей, когда они используют программу.Я хотел бы, чтобы текстовая область автоматически прокручивалась до самой нижней записи (самой новой) при добавлении новой строки (или сообщения для пользователя).Я реализовал это:

 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 );

Этот код прокручивает вертикальную полосу прокрутки до конца элемента управления EDIT после добавления нового сообщения и прекрасно работает, полоса прокрутки прокручивается, но текст по-прежнему остается видимым с начала- после добавления он перематывается в начало, а полоса прокрутки - назад.Как сделать это правильно?

Последнее, но не менее важное - это может быть важно - для того, чтобы отобразить сообщение, сначала я фиксирую текст, который уже отображается, используя: GetDlgItemText (h2, ID_EDIT_CONSOLE, buf, len+ 1);затем я конвертирую buf в строку и добавляю к этой строке новое сообщение, которое я хочу отобразить.Затем я конвертирую его обратно в массив символов и устанавливаю его с помощью SetDlgItemText.Я разделяю строки, используя \ r \ n.Я кодировал это таким образом, потому что я не знал, как добавить строку в элемент управления EDIT иначе, чем с помощью SetDlgItemText.И он добавляет только одну запись AFAIK - при двойном использовании я не буду добавлять две записи, добавленные в элемент управления EDIT, но первая будет заменена вторым вызовом функции.

Ответы [ 5 ]

6 голосов
/ 09 апреля 2015

У меня была та же проблема, и я решил ее с помощью ответа Джерри Коффина и некоторых исследований.Теперь я использую этот способ:

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
6 голосов
/ 20 февраля 2012

Не используйте SetScrollInfo. Используйте SendMessage() с сообщением EM_LINESCROLL , отправляя сообщение в дескриптор окна элемента редактирования.

SendMessage(MemoHwnd, EM_LINESCROLL, 0, NumLinesToScroll);

В документации сказано:

Элемент управления не прокручивается вертикально за последней строкой текста в элементе редактирования. Если текущая строка плюс количество строк, указанное параметром lParam, превышает общее количество строк в элементе управления редактированием, значение корректируется таким образом, что последняя строка элемента управления для редактирования прокручивается до верхней части окна элемента управления для редактирования.

2 голосов
/ 20 февраля 2012

Вы можете добавить текст, установив начало и конец выделения в конец текста в элементе управления ( EM_SETSEL ), а затем заменив (пустой) выбор новым текстом ()EM_REPLACESEL ).

Прокрутить до нижней части можно с помощью EM_SCROLLCARET после того, как курсор (выбор) находится в конце текста.Есть и другие способы, но если вы делаете это сразу после добавления текста, это, вероятно, самый простой способ.

0 голосов
/ 30 января 2019

в моем случае у меня была многострочная строка, и идея Кена Уайта сработала очень хорошо: 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); }

0 голосов
/ 31 августа 2017

для проектов 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
...