Delphi 7 печать на турецком языке

У меня есть некоторый устаревший код (1 миллион строк), написанный на Delphi 7 Pascal, который по разным причинам не может быть обновлен до более поздней версии Delphi. Программа выводит документы примерно на 30 языках и делает очень хорошую работу по созданию различных символов на всех языках, кроме турецкого. Кодирование устанавливает кодировку в TURKISH_CHARSET (162). Когда он пытается напечатать char #351 (ş, hex 15f), char #285 (ğ, hex 11f) или char #305 (ı, hex 131), он печатает только "s", "g" или "i". Он использует простой

Printer.Canvas.TextOut(x, y, sText)  

вывести текст.

Я пытался скомпилировать код на разных машинах и запустить его на разных версиях Windows, но всегда с одним и тем же результатом.

1 ответ

В Delphi 7 string это псевдоним для AnsiString, который кодирует символы Unicode в виде 8-битных байтов, используя кодовые страницы Windows. В некоторых кодовых страницах MBCS для символов Unicode может потребоваться несколько байтов (хотя турецкий не является одним из них).

У Microsoft есть несколько кодовых страниц для турецкого языка:

  • 857 (MS-DOS)
  • 1254 (Windows)
  • 10081 (Macintosh)
  • 28599 (ISO-8859-9)

В обеих кодовых страницах 1254 и 28599 (где 1254 - наиболее вероятная из тех, с которыми вы столкнетесь), рассматриваемые символы Unicode кодируются в 8-битном виде как шестнадцатеричное $FE (ş), $F0 (ğ), а также $FD (ı).

Убедитесь, что ваш sText Строковая переменная фактически содержит эти байтовые значения, а не байты ASCII. $73 (s), $67 (g), а также $69 (i) вместо Если он содержит последнее, вы теряете турецкие данные еще до того, как они достигнут Canvas.TextOut(), Это было бы проблемой ранее в вашем коде.

Однако если sText содержит правильные байты, то проблема должна быть на стороне ОС, так как TCanvas.TextOut() это просто тонкая оболочка для Win32 API ExtTextOutA() функция, где sText передается как есть в API. Возможно, используемый вами шрифт не поддерживает турецкий язык или, по крайней мере, эти символы. Или может быть проблема с драйвером принтера. В любом случае, вам, возможно, придется прибегнуть к sText значение для WideString с помощью MultiByteToWideChar() а затем позвоните ExtTextOutW() (не ExtTextOutA()) непосредственно, например:

var
  wText: WideString;
  size: TSize;
begin
  //Printer.Canvas.TextOut(x, y, sText);
  SetLength(wText, MultiByteToWideChar(1254{28599}, 0, PAnsiChar(sText), Length(sText), nil, 0));
  MultiByteToWideChar(1254{28599}, 0, PAnsiChar(sText), Length(sText), PWideChar(wText), Length(wText)));
  Windows.ExtTextOutW(Printer.Canvas.Handle, x, y, Printer.Canvas.TextFlags, nil, PWideChar(wText), Length(wText), nil);
  size.cX := 0;
  size.cY := 0;
  Windows.GetTextExtentPoint32W(Printer.Canvas.Handle, PWideChar(wText), Length(wText), size);
  Printer.Canvas.MoveTo(x + size.cX, Y);
end;
Другие вопросы по тегам