Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Записать в файл текст из Edit в юникоде


Автор: Chewits 4.11.2010, 17:20
Пишу что-то типа простейшего текстового редактора.
Написал функцию вызова диалога сохраненя файла (как это рекомендуется делать для последних версий windows)

Код

HANDLE OpenSaveFile(HWND hWnd)
{
    IFileSaveDialog *pFileSaveDialog;
    
    HRESULT hr = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFileSaveDialog));
    HANDLE hf;

    if (SUCCEEDED(hr))
    {
        hr = pFileSaveDialog -> Show(NULL);

        if (SUCCEEDED(hr))
        {
            IShellItem *psiCurrent = 0;
            hr = pFileSaveDialog -> GetResult(&psiCurrent);

            if (SUCCEEDED(hr))
            {
                LPTSTR pszPath = 0;
                hr = psiCurrent -> GetDisplayName(SIGDN_FILESYSPATH, &pszPath);

                if (SUCCEEDED(hr))
                {
                    hf = CreateFile(pszPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
                    CoTaskMemFree(pszPath);
                    return hf;
                }

                psiCurrent -> Release();
            }
        }
    }

    return 0;
}


Она возвращает дескриптор на открытый файл, с которым потом работаю при получении сообщения от кнопки "Сохранить". Есть кроме этого также контрол типа "edit", в нём текст, который и нужно сохранить. Вот код, который выполняется при получении сообщения от кнопки:

Код

                case ID_SAVE:
                {
                    DWORD dwBytesToWrite;
                    DWORD dwBytesWritten;
                    PTCHAR npTextBuffer;
                    HANDLE hf = OpenSaveFile(hWnd);

                    if (hf == INVALID_HANDLE_VALUE)
                        break;

                    dwBytesToWrite = GetWindowTextLength(hEdit);
                    npTextBuffer = (PTCHAR)LocalLock((HANDLE)SendMessage(hEdit, EM_GETHANDLE, 0, 0L));

                    if (!WriteFile(hf, npTextBuffer, dwBytesToWrite, &dwBytesWritten, NULL))
                    {
                        CloseHandle(hf);
                        MessageBox(hWnd, (LPCTSTR)L"Ошибка при сохранении файла!", (LPCTSTR)L"Error", MB_OK | MB_ICONWARNING);
                    }

                    if (dwBytesWritten != dwBytesToWrite)
                        MessageBox(hWnd, (LPCTSTR)L"Файл записан не поностью!", (LPCTSTR)L"Error", MB_OK | MB_ICONWARNING);

                    CloseHandle(hf);
                    LocalUnlock(hTxtBuf);
                    bUpdate = FALSE;
                    break;
                }


При записи вместе с каждым символом записывается еще один байт, какой-то лишний, как я понимаю, например ввожу в "edit": "test. test. test." (17 символов), в файл записывается "tNULeNULsNULtNUL.NUL NULtNULeNULs" (если смотреть в Notepad++)
Если по-русски вводить "тест. тест. тест.", то и с самими символами проблемы, получится "BEOT5EOTAEOTBEOT.NUL NULBEOT5EOTA"

Куда смотреть, что добавить, чтобы правильно работало с юникодом (или, правильнее, с широкими символами)?

Автор: Alca 4.11.2010, 18:16
Можно Юникод перегнать в АНСИ.

P.S.
WriteFile пишет побайтово, а не посимвольно.

Автор: xvr 5.11.2010, 15:10
Цитата(Chewits @  4.11.2010,  17:20 Найти цитируемый пост)
При записи вместе с каждым символом записывается еще один байт, какой-то лишний, как я понимаю, например ввожу в "edit": "test. test. test." (17 символов), в файл записывается "tNULeNULsNULtNUL.NUL NULtNULeNULs" (если смотреть в Notepad++)
Если по-русски вводить "тест. тест. тест.", то и с самими символами проблемы, получится "BEOT5EOTAEOTBEOT.NUL NULBEOT5EOTA"
Вполне такой кошерный Unicode файл  smile Еще ему метку Unicode вначале пропишите, и вообще будет правильный со всех сторон файл.  smile 

Если же вам нужен ASCII (или например UTF-8), то надо конвертировать (http://msdn.microsoft.com/en-us/library/dd374130%28VS.85%29.aspx)


Автор: Estranged 5.11.2010, 18:04
http://msdn.microsoft.com/en-us/library/ms633521%28VS.85%29.aspx см Return Value и Remarks. Неправильный размер передается в WriteFile.

 

Автор: bass 8.11.2010, 20:10
Builder 100% работает.

String Buff =Form1->Edit1->Text;
WriteFile(hf, &Buff[1], Buff.Lenght, &dwBytesWritten, NULL))

Автор: xvr 8.11.2010, 21:39
Цитата(bass @  8.11.2010,  20:10 Найти цитируемый пост)
Builder 100% работает.
Под 2010 проверьте, вас ждет много удивительного  smile 

Автор: Chewits 9.11.2010, 00:18
Спасибо всем)

дописал примерно следующее:

Код

// сколько записывать в байтах
dwBytesToWrite = WideCharToMultiByte(CP_UTF8, 0, npTextBuffer, dwCharsToWrite, NULL, 0, NULL, NULL );
// новая строка для записи
LPSTR lpMultiByteStr = new CHAR[dwBytesToWrite];
// помещается в lpMultiByteStr конвертированая строка
WideCharToMultiByte(CP_UTF8, 0, npTextBuffer, dwCharsToWrite, lpMultiByteStr, dwBytesToWrite, NULL, NULL );
...// запись в файл и пр.
delete []lpMultiByteStr;


работает smile а метку utf-8 в начале файла таки надо приписывать?) там 4 байта вроде какие-то?

Автор: xvr 9.11.2010, 10:54
Цитата(Chewits @  9.11.2010,  00:18 Найти цитируемый пост)
а метку utf-8 в начале файла таки надо приписывать
По желанию. 
Цитата

там 4 байта вроде какие-то?
3 байта: ef bb bf

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)