Delphi - хранит WideStrings внутри программы - PullRequest
0 голосов
/ 15 августа 2011

Раньше я использовал INI-файлы для хранения текста в Юникоде, но теперь мне нужно хранить текст в Юникоде в исполняемом файле.Как мне этого добиться?

Я хочу хранить эти буквы:

āčēūīšķļņž

Ответы [ 3 ]

3 голосов
/ 15 августа 2011

Если вы хотите сохранить INI-файлы Unicode, вы можете попробовать следующий код.Файлы сохраняются в UTF8 кодировке .

Также вы можете взглянуть на эту библиотеку Unicode , где вы можете найти множество вспомогательных функций.

uses IniFiles;

function WideStringToUTF8(const Value: WideString): AnsiString;
var
  BufferLen: Integer;
begin
  Result := '';

  if Value <> '' then
  begin
    BufferLen := WideCharToMultiByte(CP_UTF8, 0, PWideChar(Value), -1, nil, 0, nil, nil);
    SetLength(Result, BufferLen - 1);
    if BufferLen > 1 then
      WideCharToMultiByte(CP_UTF8, 0, PWideChar(Value), -1, PAnsiChar(Result), BufferLen - 1, nil, nil);
  end;
end;

function UTF8ToWideString(const Value: AnsiString): WideString;
var
  BufferLen: integer;
begin
  Result := '';

  if Value <> '' then
  begin
    BufferLen := MultiByteToWideChar(CP_UTF8, 0, PAnsiChar(Value), -1, nil, 0);
    SetLength(Result, BufferLen - 1);
    if BufferLen > 1 then
      MultiByteToWideChar(CP_UTF8, 0, PAnsiChar(Value), -1, PWideChar(Result), BufferLen - 1);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  IniFile: TIniFile;
const
  UnicodeValue = WideString(#$0101#$010D#$0113#$016B#$012B#$0161);
begin
  IniFile := TIniFile.Create('C:\test.ini');

  try
    IniFile.WriteString('Section', 'Key', WideStringToUTF8(UnicodeValue));
    IniFile.UpdateFile;
  finally
    IniFile.Free;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  IniFile: TIniFile;
  UnicodeValue: WideString;
begin
  IniFile := TIniFile.Create('C:\test.ini');

  try
    UnicodeValue := UTF8ToWideString(IniFile.ReadString('Section', 'Key', 'Default'));
    MessageBoxW(Handle, PWideChar(UnicodeValue), 'Caption', 0);
  finally
    IniFile.Free;
  end;
end;

enter image description here
с Delphi 2007 на 64-битной Windows 7 Enterprise SP 1

2 голосов
/ 15 августа 2011

Если вам определенно нужно использовать Delphi 7, есть несколько вариантов:

  1. Хранить строки в ресурсах, связанных с исполняемым файлом.

  2. Храните строки в большом блокноте или в том же самом месте, расположенном в глобальном модуле данных или любом другом визуальном или невизуальном компоненте, и обращайтесь к нему по индексу. Это возможно, потому что строки в ресурсах Delphi хранятся в XML-кодированной форме. Например. пример ваших символов āčēūīšķļņž будет сохранен как &#257;&#269;&#275;&#363;&#299;&#353;&#311;&#316;&#326;&#382;

  3. Храните строки в кодировке XML или Base64 в строковых константах внутри вашего кода.

Для преобразования строк вы можете использовать EncdDecd.pas, xdom.pas или некоторые функции System.pas, такие как UTF8Encode / UTF8Decode.

Для отображения и редактирования строк Unicode в формах Delphi вы можете использовать специальный набор элементов управления Unicode, таких как Элементы управления Unicode TNT или подкласс исходных элементов управления Delphi и выполнять некоторые другие обходные пути самостоятельно, как описано в этом отрывке из комментариев. в TntControls.pas (часть элементов управления TNT Unicode):

Windows NT обеспечивает поддержку собственных окон Unicode. Добавить Поддержка Unicode для Потомок TWinControl, переопределить CreateWindowHandle () и вызвать CreateUnicodeHandle ().

Одна из основных причин, по которой это работает, заключается в том, что VCL использует только ANSI версия SendMessage () - SendMessageA (). Если вы позвоните SendMessageA () на UNICODE окно, Windows имеет дело с преобразованием ANSI / UNICODE автоматически. Так например, если VCL отправляет WM_SETTEXT в окно, используя SendMessageA, Windows на самом деле ожидает PAnsiChar, даже если целевое окно ЮНИКОД окно. Поэтому вызов SendMessageA с PChars не вызывает проблем.

Проблема в VCL связана с методом TControl.Perform (). Выполнить () Вызывает оконную процедуру напрямую и принимает окно ANSI. Это проблема, если, например, VCL вызывает Perform (WM_SETTEXT, ...) проходя в PAnsiChar, который в конечном итоге передается в DefWindowProcW () который ожидает PWideChar.

Это причина для SubClassUnicodeControl (). Эта процедура подкласс Windows WndProc и указатель TWinControl.WindowProc. Будет определить, если сообщение пришло из Windows или если WindowProc был вызван непосредственно. Тогда будет вызовите SendMessageA () для Windows, чтобы выполнить правильное преобразование на некоторые текстовые сообщения.

Другая проблема связана с TWinControl.DoKeyPress (). это вызывается из WM_CHAR сообщение. Он бросает WideChar в AnsiChar и отправляет результирующий символ DefWindowProc. Чтобы избежать этого, DefWindowProc также подкласс. WindowProc сделает сообщение WM_CHAR безопасным для кода обработки ANSI преобразование кода символа в #FF, прежде чем передать его. Это сохраняет оригинальный WideChar в .Неиспользуемое поле TWMChar. Код #FF преобразуется обратно в WideChar перед передачей на DefWindowProc.

0 голосов
/ 15 августа 2011

До

const MyString = WideString('Teksts latvie'#$0161'u valod'#$0101);
...