SendMessage WM_GETTEXT and WM_GETTEXTLENGTH have significantly different characters

Asked 2 years ago, Updated 2 years ago, 111 views

while(true) {//<=Actually some condition
    /* Some action, but hwnd text is not fiddled with on the code side */
    // hwnd<- Handle of interest
    varsb = new StruingBuilder();
    var length = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
    sb.Capacity=length+1;//Additional 2
    Console.WriteLine("before length:"+length);
    Thread.Sleep(200); // Same without
    length = SendMessage(hwnd, WM_GETTEXT, length+1, sb);
    Console.WriteLine("before length:"+length);
    /* Some action, but hwnd text is not fiddled with on the code side */
}

Running the above program

before length:212
after length —91

It happens many times.
Also, the latest version of the target application matches the number of characters in any situation, but the older version may or may not match as described above.
What are the possible causes?Thank you for your cooperation.

Note:
The sb contained a truncated actual string.

Note 2:
I set the capacity of sb, but it was omitted due to a transcription error.I am very sorry to hear from you.I'm sorry.

Note 3:
As shown below, I changed the length (length*10) to be retrieved as a trial, but the string I got was still cut off.

while(true) {//<=Actually some condition
    /* Some action, but hwnd text is not fiddled with on the code side */
    // hwnd<- Handle of interest
    varsb = new StruingBuilder();
    var length = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
    sb.Capacity=length*10+1;
    Console.WriteLine("before length:"+length);
    Thread.Sleep(200); // Same without
    length = SendMessage (hwnd, WM_GETTEXT, length * 10 + 1, sb);
    Console.WriteLine("before length:"+length);
    /* Some action, but hwnd text is not fiddled with on the code side */
}

c# windows .net winapi

2022-09-30 17:20

2 Answers

Described in WM_GETTEXTLENGTH.

Under certain conditions, the DefWindowProc function returns a value that is larger than the actual length of the text. This occurs with certain mixtures of ANSI and Unicode, and is due to the system allowing for the possible existence of double-byte character set (DBCS) characters within the text. The return value, however, will always be at least as large as the actual length of the text; you can thus always use It to guide buffer allocation. This behavior can occur when an application uses both ANSI functions and common dialogs, which use Unicode.

There are two types of Windows applications, Unicode and ANSI, and two versions of the API are available.If the application's operating mode differs from the SendMessage, it returns a large buffer size that can store strings instead of the actual number of characters.

The sb contained a truncated actual string.
SendMessage is DllImport("user32.dll", CharSet=CharSet.Auto)

WM_GETTEXTLENGTH naturally returns the number of bytes in the ANSI string when the ANSI version is called, and the buffer size that WM_GETTEXT requires in WPARAM also depends on the version it called.However, the buffer size that StringBuilder maintains is always Unicode characters.The code listed in the questionnaire is very unstable because the buffer size units do not match.

In addition to consistent Unicode, WM_GETTEXT should have a buffer size of StringBuilder before calling.In addition, the default buffer size for StringBuilder is 16 characters, so it is often overflowing.

 [DllImport("user32.dll", CharSet=CharSet.Unicode]
static external int SendMessage (IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
DllImport("user32.dll", CharSet=CharSet.Unicode)
static external int SendMessage (IntPtr hwnd, int msg, IntPtr wparam, StringBuilder lparam);

while(true) {//<=Actually some condition
    /* Some action, but hwnd text is not fiddled with on the code side */
    // hwnd<- Handle of interest
    var length = SendMessage (hwnd, WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
    Console.WriteLine("before length:"+length);
    varsb = new StringBuilder (length); /* Ensure buffer size for length*/
    length = SendMessage(hwnd, WM_GETTEXT, new IntPtr(length+1), sb);
    Console.WriteLine("before length:"+length);
    /* Some action, but hwnd text is not fiddled with on the code side */
}


2022-09-30 17:20

What are the possible causes?

Under the following conditions, there may be no discrepancy between the two return values:

(1) The acquired side window is made of MBCS (=ANSI).
(2)The side window to be retrieved is made by Unicode.

In this case,

(1) The side returns the number of characters (=the number of BYTEs) per MBCS to WM_GETTEXTLENGTH.
Replace this with length (=byTE count).
Note that the number of unicode characters in the buffer is passed when WM_GETTEXT is sent later.

However, the (1) side interprets wParam in the WM_GETTEXT argument as the number of BYTEs in the buffer.
(Note that it is not a UNIXODE character count)

Therefore, when (1) returns the result of converting the MBCS string that it holds to Unicode to sb,

It is interpreted as insufficient (actually sufficient) buffers. Copy approximately half of the UNCODE-converted strings and
Return the number of MBCS characters (=byTE).

Isn't it?


2022-09-30 17:20

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.