GetWindowTextLength возвращает 0, когда текст находится в элементе управления редактированием

#c #winapi #utf-8

#c #winapi #utf-8

Вопрос:

Я пишу текстовый редактор, и у меня возникли некоторые проблемы с сохранением файлов в формате utf-8. У меня есть функция, которая считывает текст из расширенного элемента управления редактированием и записывает его в файл, используя флаг, переданный функции, который зависит от пользовательских настроек. Это может быть utf-16, ascii или utf-8. Оба сегмента записи файлов в формате utf-16 и ascii работают нормально и создают допустимые файлы. Проблема заключается в том, что в следующем блоке кода вызов GetWindowTextLength всегда возвращает 0. Таким образом, в результате ничего не извлекается из окна или не записывается в файл.

  HANDLE hFile;
 if ((hFile = CreateFile (pstrFileName, GENERIC_WRITE, 0, 
      NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE) {
      return FALSE;
 }

 int    iLength = 0;
 DWORD  dwBytesWritten = 0;

 switch (encoding) {

/*other text encoding cases*/

     case ID_SETTINGS_UTF_8: {
        try {
            iLength = GetWindowTextLength(hwndEdit);  //returns 0

            unique_ptr<wchar_t> wide_buf(new wchar_t[iLength   1]);
            GetWindowTextW(hwndEdit, wide_buf.get(), iLength   1);

            int bytes_needed = WideCharToMultiByte(CP_UTF8, WC_COMPOSITECHECK |
                WC_DEFAULTCHAR | WC_NO_BEST_FIT_CHARS, wide_buf.get(), -1,
                NULL, 0, NULL, NULL);

            unique_ptr<char> utf8_buf(new char[bytes_needed]);

            WideCharToMultiByte(CP_UTF8, WC_COMPOSITECHECK |
                WC_DEFAULTCHAR | WC_NO_BEST_FIT_CHARS, wide_buf.get(), -1,
                utf8_buf.get(), bytes_needed, NULL, NULL);

            WriteFile(hFile, utf8_buf.get(), bytes_needed, 
                        amp;dwBytesWritten, NULL);

            if (bytes_needed != dwBytesWritten) {
                        CloseHandle (hFile);
                         return FALSE;
            }

             CloseHandle (hFile) ;
             return TRUE;
        } catch (bad_allocamp; ba) {
            UNREFERENCED_PARAMETER(ba);
            CloseHandle (hFile);
            return FALSE;
        }
    }
    break;
  

Комментарии:

1. Здесь действительно проблема с дизайном. Вызов GetWindowTextLength действительно не должен быть уникальным для кода UTF-8. Вы должны получить текст в формате UTF-16 из окна в общей части. Аналогично, WriteFile вызов и его обработка ошибок также должны выполняться в обычном коде — в этом тоже нет UTF-8.

2. Пара вопросов по устранению неполадок: в случае, когда GetWindowTextLength() возвращает 0, если вы передаете буфер разумного размера в GetWindowText() возвращает ли он что-нибудь? GetLastError() Сообщает ли что-нибудь интересное (возможно, вызовите SetLastError(0) раньше, чтобы попытаться предотвратить чтение устаревшего кода ошибки)?

3. Проверьте hwnd рассматриваемой редактуры форматированного текста, убедитесь, что это правильный hwnd в том месте, где вызывается GetWindowTextLength

Ответ №1:

Вы повреждаете кучу. new[] должно совпадать с delete[] , не delete .

Проще просто использовать std::vector :

 std::vector<wchar_t> wide_buf(iLength   1);
//...
std::vectorchar> utf8_buf(bytes_needed);
  

Комментарии:

1. Теперь я понимаю, что вы говорите об удалении, после более внимательного прочтения unique_ptr. Это решается путем изменения спецификации типа на unique_ptr<wchar_t[]> . Но вызов GetWindowTextLength по-прежнему возвращает 0, когда кодировка помечена как utf-8.

2. Кажется, я вспоминаю, что MSVC6 был терпим к такому злоупотреблению delete

Ответ №2:

Ваше приложение скомпилировано в формате UNICODE или ANSI? (вы используете объявления GetWindowTextLength и GetWindowTextW)

Можете ли вы показать код для ANSI и для UTF-16 (где вы получите правильный результат).