Из MSDN:
LB_GETTEXTLEN
Возвращаемое значение - это длина строки в TCHAR, за исключением завершающего нулевого символа. При определенных условиях это значение может фактически превышать длину текста. Для получения дополнительной информации см. Следующий раздел «Примечания».
LB_GETTEXT
Указатель на буфер, который получит строку; это тип LPTSTR, который впоследствии приводится к LPARAM. В буфере должно быть достаточно места для строки и завершающего нулевого символа. Сообщение LB_GETTEXTLEN может быть отправлено до сообщения LB_GETTEXT, чтобы получить длину строки в TCHAR.
Вам необходимо выделить место для одного дополнительного нулевого TCHAR. Однако я вижу несколько других проблем в вашем коде:
- Ваша система WinNT? Затем lb_gettextlen возвращает длину в TCHAR, а в системах NT один TCHAR имеет длину два байта
- Я вижу AllocHGlobal, но я не вижу FreeHGlobal. Утечка памяти?
- Почему вы конвертируете байтовый массив в строку, используя кодировку UTF8? Вам нужно использовать Unicode.
- Ваш интерфейс SendMessage потенциально опасен, потому что он не ожидает указателей x64.
Обновление: В целом ваш код должен выглядеть следующим образом:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam,
[MarshalAs(UnmanagedType.LPTStr)] StringBuilder lParam);
private void Form1_Shown(object sender, EventArgs e)
{
int count = (int)SendMessage(_chatHwnd, WinApi.LB_GETCOUNT, IntPtr.Zero, IntPtr.Zero);
StringBuilder sb = new StringBuilder(count * 20);
for (int i = _lastReadPosition; i < count; i++)
{
int len = (int)SendMessage(_chatHwnd, WinApi.LB_GETTEXTLEN, (IntPtr)i, IntPtr.Zero);
StringBuilder LineBuilder = new StringBuilder(len + 1);
SendMessage(_chatHwnd, WinApi.LB_GETTEXT, (IntPtr)i, LineBuilder);
sb.Append(LineBuilder.ToString());
}
}