1

RichEdit has a strange behavior. The WM_GETTEXTLENGTH message considers the new line characters as two characters \r\n, while the EM_SETSEL and EM_EXSETSEL messages consider them as one character \n.

This creates confusion and lot of bad things, for example the below function does not work well:

void CutLastFiveChars(HWND hRichEdit) {

    // Get the current text length
    int textLength = (int)SendMessage(hRichEdit, WM_GETTEXTLENGTH, 0, 0);

    // Calculate the starting position for the selection
    int startPos = textLength - 5;
    if (startPos < 0) {
        startPos = 0;  // Ensure startPos is within bounds
    }

    // Set the selection to the last 5 characters
    SendMessage(hRichEdit, EM_SETSEL, startPos, textLength);

    // Replace the selected text with an empty string
    SendMessage(hRichEdit, EM_REPLACESEL, TRUE, (LPARAM)"");
}

How can I fix this?

Or, is there a way to disable automatically converting \n characters into \r\n?

Alex Veres
  • 29
  • 2
  • https://learn.microsoft.com/en-us/windows/win32/controls/em-gettextlengthex – Hans Passant Jul 04 '23 at 18:29
  • For histerical reasons the line ending for RichEdit is a single linefeed, not carriage return+line feed as is common in the winapi. WM_GETTEXTLENGTH dutifully hides that distinction, giving you a value that assumes you'll use WM_GETTEXT or GetWindowText() to retrieve the text with proper line endings. But not what you want here, send EM_GETTEXTLENGTHEX to get the actual length. – Hans Passant Jul 04 '23 at 20:12
  • I tested with Riched20.dll and RICHEDIT_CLASS, result for me is 2 chars more for each line. Check this https://stackoverflow.com/questions/38441090/em-gettextex-wrongly-documented-return-value – Alex Veres Jul 04 '23 at 20:31
  • Thanks Hans Passant, works with EM_GETTEXTLENGTHEX – Alex Veres Jul 04 '23 at 21:30
  • There is still a problem with EM_EXSETSEL and EM_SETSEL because the counting is done as if the separation lines have only one character and in fact there are two. – Alex Veres Jul 05 '23 at 05:55

2 Answers2

1

As @HansPassant pointed, EM_GETTEXTLENGTHEX gets the actual length with considering the new line characters as one character \r which is the same way as the EM_SETSEL and EM_EXSETSEL messages. While WM_GETTEXTLENGTH considers the new line characters as two characters \r \n.

You just need to use the EM_SETSEL and EM_EXSETSEL messages with EM_GETTEXTLENGTHEX. Then if you want to select a number of characters strictly, you need some extra effort. For example, revise the first selection based on EM_GETTEXTEX. enter image description here

YangXiaoPo-MSFT
  • 1,589
  • 1
  • 4
  • 22
-1

Have you made any attempt to read the manual carefully?

WM_GETTEXTLENGTH is used for getting a buffer allocation size.

To obtain the exact length of the text, use the WM_GETTEXT, LB_GETTEXT, or CB_GETLBTEXT messages, or the GetWindowText function.

273K
  • 29,503
  • 10
  • 41
  • 64
  • 1. The question is how to correctly get the length of the text, not the text. 2. You test yourself or only quote from documentation ? 3. Return for me is 2 chars more for each line, not "The return value is the length of the text in characters, not including the terminating null character.". Maybe in documentation is something wrong. I tested with Riched20.dll and RICHEDIT_CLASS – Alex Veres Jul 04 '23 at 19:54