2016-08-23 2 views
0

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

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

для вывода текста.

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

+0

Настаивая на использовании ANSI закодированный текст в 2016 году глупо. –

+0

Когда я google TURKISH_CHARSET, я нахожу, что это соответствует кодовой странице 1254. Когда я нахожу код страницы 1244, я вижу таблицу символов. Похоже, что коды для этих символов - $ FE, $ F0 и $ FD. –

+0

TextOut принимает строковый параметр, который в Delphi 7 означает ansistring. Каждый символ в ansistring - один байт. –

ответ

0

В 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 содержит правильные байты, то проблема должна быть на стороне OS, так как TCanvas.TextOut() это просто тонкая оболочка для API ExtTextOutA() функции Win32, где 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; 
+0

Спасибо, Реми, это действительно полезно. Я написал небольшую функцию, которая отвлекает любые попытки распечатать турецкий язык и помещает текст в формат WideString с помощью процедур печати WideString (как в вашем коде выше). Все вышло отлично :-) –

Смежные вопросы