Difference between revisions of "LCL Unicode Support/ja"

From Lazarus wiki
Jump to navigationJump to search
Line 12: Line 12:
  
 
注意:細かい実装については、いま議論の最中ですので、この文書の内容は変わる可能性があります。
 
注意:細かい実装については、いま議論の最中ですので、この文書の内容は変わる可能性があります。
 +
 +
== Instructions for users ==
 +
 +
In unicode widgetsets it's important to note that not everything is unicode. The Free Pascal Runtime Library, the Free Pascal FCL library are ansi. It's the responsibility of the developer to know what is the encoding of their strings and do the proper conversion between libraries which expect different encodings.
 +
 +
Usually the encoding is per-library. Each library will uniformly expect 1 kind of encoding, which will usually either be unicode (UTF-8 for Lazarus) or Ansi (which means the system encoding, and may be utf-8 or not). The RTL and the FCL of FPC 2.2.2 expect ansi strings. FPC 2.3.x currently too.
 +
 +
You can can convert between unicode and ansi using the UTF8ToAnsi and AnsiToUTF8 functions from the System unit or the UTF8ToSys and SysToUTF8 from the FileUtil unit. The later two are smarter but pull more code into your program.
 +
 +
Examples:
 +
 +
Say you get a string from a TEdit and you want to give it to some rtl file routine:
 +
 +
<delphi>
 +
var
 +
  MyString: string; // utf-8 encoded
 +
begin
 +
  MyString := MyTEdit.Text;
 +
  SomeRTLRoutine(UTF8ToAnsi(MyString));
 +
end;
 +
</delphi>
 +
 +
And for the opposite direction:
 +
 +
<delphi>
 +
var
 +
  MyString: string; // ansi encoded
 +
begin
 +
  MyString := SomeRTLRoutine;
 +
  MyTEdit.Text := AnsiToUTF8(MyString);
 +
end;
 +
</delphi>
 +
 +
'''Important''': UTF8ToAnsi will return an empty string if the UTF8 string contains invalid characters.
 +
 +
'''Important''': AnsiToUTF8 and UTF8ToAnsi require a widestring manager under Linux, BSD and Mac OS X. You can use the SysToUTF8 and UTF8ToSys functions (unit FileUtil) or add a the widetstring manager by adding cwstring as one of the first units to your program's uses section.
 +
 +
 +
===Dealing with directory and filenames===
 +
 +
Lazarus controls and functions expect filenames and directory names in utf-8 encoding, but the RTL uses ansi strings for directories and filenames.
 +
 +
For example, consider a button, which sets the Directory property of the TFileListBox to the current directory. The RTL Function [[doc:rtl/sysutils/getcurrentdir.html|GetCurrentDir]] is ansi, and not unicode, so conversion is needed:
 +
 +
<delphi>
 +
procedure TForm1.Button1Click(Sender: TObject);
 +
begin
 +
  FileListBox1.Directory:=SysToUTF8(GetCurrentDir);
 +
  // or use the functions from the FileUtil unit
 +
  FileListBox1.Directory:=GetCurrentDirUTF8;
 +
end;
 +
</delphi>
 +
 +
The unit FileUtil defines common file functions with UTF-8 strings:
 +
 +
<Delphi>
 +
// basic functions similar to the RTL but working with UTF-8 instead of the
 +
// system encoding
 +
 +
// AnsiToUTF8 and UTF8ToAnsi need a widestring manager under Linux, BSD, MacOSX
 +
// but normally these OS use UTF-8 as system encoding so the widestringmanager
 +
// is not needed.
 +
function NeedRTLAnsi: boolean;// true if system encoding is not UTF-8
 +
procedure SetNeedRTLAnsi(NewValue: boolean);
 +
function UTF8ToSys(const s: string): string;// as UTF8ToAnsi but more independent of widestringmanager
 +
function SysToUTF8(const s: string): string;// as AnsiToUTF8 but more independent of widestringmanager
 +
 +
// file operations
 +
function FileExistsUTF8(const Filename: string): boolean;
 +
function FileAgeUTF8(const FileName: string): Longint;
 +
function DirectoryExistsUTF8(const Directory: string): Boolean;
 +
function ExpandFileNameUTF8(const FileName: string): string;
 +
function ExpandUNCFileNameUTF8(const FileName: string): string;
 +
{$IFNDEF VER2_2_0}
 +
function ExtractShortPathNameUTF8(Const FileName : String) : String;
 +
{$ENDIF}
 +
function FindFirstUTF8(const Path: string; Attr: Longint; out Rslt: TSearchRec): Longint;
 +
function FindNextUTF8(var Rslt: TSearchRec): Longint;
 +
procedure FindCloseUTF8(var F: TSearchrec);
 +
function FileSetDateUTF8(const FileName: String; Age: Longint): Longint;
 +
function FileGetAttrUTF8(const FileName: String): Longint;
 +
function FileSetAttrUTF8(const Filename: String; Attr: longint): Longint;
 +
function DeleteFileUTF8(const FileName: String): Boolean;
 +
function RenameFileUTF8(const OldName, NewName: String): Boolean;
 +
function FileSearchUTF8(const Name, DirList : String): String;
 +
function FileIsReadOnlyUTF8(const FileName: String): Boolean;
 +
function GetCurrentDirUTF8: String;
 +
function SetCurrentDirUTF8(const NewDir: String): Boolean;
 +
function CreateDirUTF8(const NewDir: String): Boolean;
 +
function RemoveDirUTF8(const Dir: String): Boolean;
 +
function ForceDirectoriesUTF8(const Dir: string): Boolean;
 +
 +
// environment
 +
function ParamStrUTF8(Param: Integer): string;
 +
function GetEnvironmentStringUTF8(Index : Integer): String;
 +
function GetEnvironmentVariableUTF8(const EnvVar: String): String;
 +
function GetAppConfigDirUTF8(Global: Boolean): string;
 +
</Delphi>
 +
 +
====Mac OS X====
 +
 +
The file functions of the FileUtil unit also take care of a Mac OS X special: OS X normalizes filenames. For example the filename 'ä.txt' can be encoded in unicode with two different sequences (#$C3#$A4 and 'a'#$CC#$88). Under Linux and BSD you can create a filename with both encodings. OS X automatically converts the a umlaut to the three byte sequence. This means:
 +
 +
<Delphi>
 +
if Filename1=Filename2 then ... // is not sufficient under OS X
 +
if AnsiCompareFileName(Filename1,Filename2)=0 then ... // not sufficient under fpc 2.2.2, even not with cwstring
 +
if CompareFilenames(Filename1,Filename2)=0 then ... // this always works (unit FileUtil or FileProcs)
 +
</Delphi>
 +
 +
===East Asian languages on Windows===
 +
 +
The default font (Tahoma) for user interface controls under Windows XP is capable of displaying correctly several languages, including arabic, russian and western languages, but not east asian languages, like chinese, japanese and korean. By going to the Control Panel, choosing Regional Settings, clicking on the Languages Tab and installing the East Asia Language Pack, the standard user interface font will simply start showing those languages correctly. Obviously Windows XP versions localized for those languages will already contain this language pack installed. Extended instructions [http://newton.uor.edu/Departments&Programs/AsianStudiesDept/Language/asianlanguageinstallation_XP.html here].
  
 
== 実装のガイドライン ==
 
== 実装のガイドライン ==

Revision as of 00:58, 5 October 2008

Deutsch (de) English (en) español (es) français (fr) 日本語 (ja) 한국어 (ko) русский (ru) 中文(中国大陆)‎ (zh_CN) 中文(台灣)‎ (zh_TW)

日本語版メニュー
メインページ - Lazarus Documentation日本語版 - 翻訳ノート - 日本語障害情報

イントロダクション

Lazarusは開発においてUnicode標準をもっとサポートする必要があります。ほとんどの場合、Windows環境においてです。 ここに、Lazarusでユニコードサポートをもっときちんとやりたい人のために、いくつかの基本的な情報を示します。このページは積極的に修正、拡張、変更していってください。

すでにユニコード標準や、DelphiでのWideStringの経験がある人にとって、Unicodeをサポートするプログラムを書く際に、このページの情報は助けになるでしょう。 以前の非ラテン言語(西方の)での利用方法や、多くの種類のキャラクタセットにとっても、また、助けになるでしょう。

注意:細かい実装については、いま議論の最中ですので、この文書の内容は変わる可能性があります。

Instructions for users

In unicode widgetsets it's important to note that not everything is unicode. The Free Pascal Runtime Library, the Free Pascal FCL library are ansi. It's the responsibility of the developer to know what is the encoding of their strings and do the proper conversion between libraries which expect different encodings.

Usually the encoding is per-library. Each library will uniformly expect 1 kind of encoding, which will usually either be unicode (UTF-8 for Lazarus) or Ansi (which means the system encoding, and may be utf-8 or not). The RTL and the FCL of FPC 2.2.2 expect ansi strings. FPC 2.3.x currently too.

You can can convert between unicode and ansi using the UTF8ToAnsi and AnsiToUTF8 functions from the System unit or the UTF8ToSys and SysToUTF8 from the FileUtil unit. The later two are smarter but pull more code into your program.

Examples:

Say you get a string from a TEdit and you want to give it to some rtl file routine:

<delphi> var

 MyString: string; // utf-8 encoded

begin

 MyString := MyTEdit.Text;
 SomeRTLRoutine(UTF8ToAnsi(MyString));

end; </delphi>

And for the opposite direction:

<delphi> var

 MyString: string; // ansi encoded

begin

 MyString := SomeRTLRoutine;
 MyTEdit.Text := AnsiToUTF8(MyString);

end; </delphi>

Important: UTF8ToAnsi will return an empty string if the UTF8 string contains invalid characters.

Important: AnsiToUTF8 and UTF8ToAnsi require a widestring manager under Linux, BSD and Mac OS X. You can use the SysToUTF8 and UTF8ToSys functions (unit FileUtil) or add a the widetstring manager by adding cwstring as one of the first units to your program's uses section.


Dealing with directory and filenames

Lazarus controls and functions expect filenames and directory names in utf-8 encoding, but the RTL uses ansi strings for directories and filenames.

For example, consider a button, which sets the Directory property of the TFileListBox to the current directory. The RTL Function GetCurrentDir is ansi, and not unicode, so conversion is needed:

<delphi> procedure TForm1.Button1Click(Sender: TObject); begin

 FileListBox1.Directory:=SysToUTF8(GetCurrentDir);
 // or use the functions from the FileUtil unit
 FileListBox1.Directory:=GetCurrentDirUTF8;

end; </delphi>

The unit FileUtil defines common file functions with UTF-8 strings:

<Delphi> // basic functions similar to the RTL but working with UTF-8 instead of the // system encoding

// AnsiToUTF8 and UTF8ToAnsi need a widestring manager under Linux, BSD, MacOSX // but normally these OS use UTF-8 as system encoding so the widestringmanager // is not needed. function NeedRTLAnsi: boolean;// true if system encoding is not UTF-8 procedure SetNeedRTLAnsi(NewValue: boolean); function UTF8ToSys(const s: string): string;// as UTF8ToAnsi but more independent of widestringmanager function SysToUTF8(const s: string): string;// as AnsiToUTF8 but more independent of widestringmanager

// file operations function FileExistsUTF8(const Filename: string): boolean; function FileAgeUTF8(const FileName: string): Longint; function DirectoryExistsUTF8(const Directory: string): Boolean; function ExpandFileNameUTF8(const FileName: string): string; function ExpandUNCFileNameUTF8(const FileName: string): string; {$IFNDEF VER2_2_0} function ExtractShortPathNameUTF8(Const FileName : String) : String; {$ENDIF} function FindFirstUTF8(const Path: string; Attr: Longint; out Rslt: TSearchRec): Longint; function FindNextUTF8(var Rslt: TSearchRec): Longint; procedure FindCloseUTF8(var F: TSearchrec); function FileSetDateUTF8(const FileName: String; Age: Longint): Longint; function FileGetAttrUTF8(const FileName: String): Longint; function FileSetAttrUTF8(const Filename: String; Attr: longint): Longint; function DeleteFileUTF8(const FileName: String): Boolean; function RenameFileUTF8(const OldName, NewName: String): Boolean; function FileSearchUTF8(const Name, DirList : String): String; function FileIsReadOnlyUTF8(const FileName: String): Boolean; function GetCurrentDirUTF8: String; function SetCurrentDirUTF8(const NewDir: String): Boolean; function CreateDirUTF8(const NewDir: String): Boolean; function RemoveDirUTF8(const Dir: String): Boolean; function ForceDirectoriesUTF8(const Dir: string): Boolean;

// environment function ParamStrUTF8(Param: Integer): string; function GetEnvironmentStringUTF8(Index : Integer): String; function GetEnvironmentVariableUTF8(const EnvVar: String): String; function GetAppConfigDirUTF8(Global: Boolean): string; </Delphi>

Mac OS X

The file functions of the FileUtil unit also take care of a Mac OS X special: OS X normalizes filenames. For example the filename 'ä.txt' can be encoded in unicode with two different sequences (#$C3#$A4 and 'a'#$CC#$88). Under Linux and BSD you can create a filename with both encodings. OS X automatically converts the a umlaut to the three byte sequence. This means:

<Delphi> if Filename1=Filename2 then ... // is not sufficient under OS X if AnsiCompareFileName(Filename1,Filename2)=0 then ... // not sufficient under fpc 2.2.2, even not with cwstring if CompareFilenames(Filename1,Filename2)=0 then ... // this always works (unit FileUtil or FileProcs) </Delphi>

East Asian languages on Windows

The default font (Tahoma) for user interface controls under Windows XP is capable of displaying correctly several languages, including arabic, russian and western languages, but not east asian languages, like chinese, japanese and korean. By going to the Control Panel, choosing Regional Settings, clicking on the Languages Tab and installing the East Asia Language Pack, the standard user interface font will simply start showing those languages correctly. Obviously Windows XP versions localized for those languages will already contain this language pack installed. Extended instructions here.

実装のガイドライン

要求事項

Lazarusの精神は、"Write once, Compile everywhere."です。 これは、理想的には、ユニコードを使うアプリケーションでは、ターゲットにむけた条件定義などがなく、1つのユニコードをサポートするソースコードで、すべてのターゲットのプログラムを生成できる、ということです。

LCLの"interface"の部分はターゲットプラットホームがユニコードをサポートするよう、ターゲットプラットホームのためのユニコードサポートを実装するべきです。そして、同時に、アプリケーションプログラマからは、プラットホームに依存している実装を隠蔽しなくてはなりません。

Lazarusに関して言えることは、アプリケーションコードとLCLの境界における内部的な文字列の通信は、LCLとWidgetsetsと同様に、古典的な(バイト並びの)stringで成り立っている、ということです。 論理的には、それらの保持には、UTF-8を使ってエンコードされているべきです。

Unicodeへの移行

LazarusではAnsiエンコーディングが、もっともよく利用されています。なぜなら、今日のGtk1とWin32のインターフェースでは、それがデフォルトでだからです。近い将来、すべてのwidgetsetはUTF-8をサポートするようになり、全てのアプリケーションはutf-8でかかれ、オブジェクトインスペクタはutf-8で動作し、utf-8に変換された文字列をインターフェースに直接渡せるようになるでしょう。

Gtk 2やQt,WinCE(将来的にはWin32U)などのように、人々が完全に動かないウイジェットセット向けのソフトウエアを開発するとき、彼らはGtkやwin32のようなもっと安定したウイジェットセットでコンパイルされたIDEを使います。 iso文字列をutf-8のためのウジェットセットに渡すような、こういった矛盾を解決するためには、ターゲットウイジェットと同じエンコーディング上で動作するIDEを使うことが必要です。これはつまり、私達はUnicodeに移行するために安定したUTF-8のIDEを必要としています。

現在、私達はエンコーディングに関して、いくつかのウイジェットセットのグループをもっています。

  • ANSIエンコーディングのインターフェース: win32 , gtk (1)
  • UTF-8エンコーディングのインターフェース: gtk (1), gtk2, qt, fpGUI
  • 現在はANSIエンコーディングだが、将来的にはUTF-8への移行が必要なインターフェース: win32, wince


gtk 1 は、ANSIとUTF-8の両方のグループであることに注意してください。理由は、Gtk1では、環境変数でそれらを決めることができるからです。 最新のLazarusでは、Win32,WinCE,gtk向けにコンパイルされた既存のソフトウエアは良く動きます。しかし、他のwidgetsetでは、エンコーディングの問題に直面します。

そして、UTF-8を使う新しいソフトウエアでは、Unicodeグループのウイジェットセットを使ってコンパイルされたものに限って動くでしょう。

重要な点は、ターゲットと同じグループでコンパイルされているIDEを使うということです。なぜなら、IDEはウイジェットセットのエンコーディングを使ってコンパイルされているからです。そして、それはターゲット向けのエンコーディングをおこなうLFMやLRSファイルを生成することができません。

ロードマップ

今、ロードマップを作成して、実行に移す時です。私達は、ガイドラインをもっています。 次のような実現可能な計画をたてました。2つのグループに仕事を分ける計画です。 1つ目は、優先的に主要な柱となる仕事を、2番目はそれ以外の仕事を計画しています。

私達が、Lazarusはユニコードが使えるよ、といえる前に、すべての主要な仕事は完全に実装されていなくてはなりません。そして、そのことが、私達の努力の最も向かう方向です。

2番目の仕事は、あったらいいな、というものです。しかし、誰かがそれらのために奉仕をしない限り、実装されることはないでしょう。

優先的に主要な仕事

Win32 Widgetset に UTF-8をサポートさせる

ノート:このステップでは、私達はすべての32ビットWindowsのバージョンを同時にターゲットとしています。この努力でつくられるすべてのコードは、この作業によって発生するバグを避けられるよう、現在のwin32インターフェースとIFDEFによって分離されるでしょう。 移行する時期になれば、IFDEFはユニコードだけが残るように除去されます。

どのようにWin9xのユニコードをサポートするかの詳細は、まだ討論中です。

状態:まだ実装されていない


Gtk 2 キーボード関数をUTF-8で動くように更新する

ノート:

状態:まだ実装されていない


Lazarus IDE が正しくWin32 ウイジェットセットで動いてUTF-8をサポートするようにする

ノート:

状態:まだ実装されていない


Lazarus IDE が正しくGtk2 ウイジェットセットで動いてUTF-8をサポートするようにする

ノート:

状態:まだ実装されていない


2番目の(その他の)仕事

Windows CE ウイジェットセットをUTF-8を使うように更新する


ノート:文字列の変換ルーチンは winceproc.ppに集約されています。多くのテストが必要です。

状態:まだ実装されていない


Gtk 1 キーボード関数をUTF-8で動くように更新する

Notes:

状態:まだ実装されていない

ユニコードの要点

ユニコード標準は、文字を0から10FFFF(h)までの整数に割り当てています。それぞれの割り当ては、コードポイントと呼ばれています。いいかえると、ユニコード文字列は、原理的には、U+000000 から U+10FFFF(0から1 114 111)までのコードポイントで定義されます。

一意のバイト順になるように、現在のユニコードのコードポイントには、3つの枠組みがあります。 これらの枠組みには、UTF-8,UTF-16,UTF-32とよばれるユニコード変換形式(訳注:Unicode transformation formats=UTF)があります。 これらの間の相互変換は可能です。

基本となる要素を示します。

                             UTF-8 UTF-16 UTF-32
最小 code point [16進]    000000 000000 000000
最大 code point  [16進]   10FFFF 10FFFF 10FFFF
Code unit size [ビット数]      8     16     32
1文字の最小バイト数              1      2      4
1文字の最大バイト数              4      4      4

UTF-8 には、いくつかの重要で便利な特徴があります。 つまり、バイト順で解釈されるので、バイトのlo-やhi-オーダーのようなものは存在しません。

(訳注:バイトのオーダーについて、8ビットを超える複数のバイトで表現する場合、バイト順をどう表現/解釈するか、プロセッサによってことなっています。CPUやハードウエア系の用語ではビッグエンディアン、リトルエンディアンとも呼ばれます。インテルのx86系プロセッサは、リトルエンディアン、PowerPCやMIPS系、Cellプロセッサはビッグエンディアンです。また、両方のエンディアンを扱えるバイエンディアンというプロセッサも存在します。ネットワーク上はビッグエンディアンが主流なため、インテルはバイトオーダーを高速にあわせるため、486以降に、BSWAP命令が追加されました。ソフトウエアでは、自由にメーカーが決めることができるため、どちらのフォーマットも存在しますが、Windowsで最初作られたソフトはリトルエンディアン、Macで最初作られたソフトはビッグエンディアンが多いようです。しかし、ユニコードのテキストファイルなどは、これらの区別をするためにBOMが設定されることがあります。)

Unicode文字のU+0000から+007F(ASCII)は、単に00hから7Fhになり、ASCIIと互換性があります。 これはすなわち、7bitのASCII文字セットしか含まないファイルや文字はASCIいとUTF-8は同じである、ということを意味します。 U+007F以上の文字は、複数のバイトの並びでエンコードされ、それぞれには、2つの最も意味のあるビットセットを持っています。(訳注:most significant bitは通常はMSB(最上位ビット)と略されます)

1文字のバイト列には、その中に他の文字の、より長いバイト列を含んでいます。 このことは、部分文字列の検索を容易にします。非アスキー文字をあらわすマルチバイトの最初のバイトは、必ずC0hからFDhの範囲にあり、これは、この文字のために、どれくらいのバイト長さがあるのか示しています。マルチバイト列における、全ての続くバイトは、80hからBFhにあります。このおかげで、再構成をしたり、堅牢なプログラムを作ることができます。

(訳注: 上記の訳の説明ではよく分からないと思いますが、デバッグの際などに知っておいたほうがいいと思うので説明すると、 utf-8形式のユニコード文字列のバイト表現は、

  • 最初のバイトが(00-7f)hは1バイト、
  • 最初のバイトが(c0-df)hの場合は2バイト、
  • 最初のバイトが(e0-ef)hの場合は3バイト、
  • 最初のバイトが(f0-f7)hの場合は4バイトで構成されています。

2文字目以降のバイトは、常に(80-bf)hであって、 JISやEUCに比べると判定などがしやすい、というを上の文章が言っている(再構成や、堅牢)のだろうと思います。

ちなみに、漢字の表現には3バイト、新拡張JISコード文字には、4バイトが必要。

日本語のテキストファイルはS-JISの1.5倍のサイズになってしまいますが、ソースコードなどは、ほとんど英文字が多いので、ファイルサイズはそれほど増えないでしょう。

訳注ここまで )


UTF-16は次のような特徴があります。: UTF-16はU+0000からU+d7ffまでの文字は1つの16bitワードを使い、その他のユニコード文字は2つの16ビットワードを使います。

最後に、UTF-32では、すべてのユニコード文字は1つの32ビットとして表現できます。

更なる情報は、こちらをみてください: Unicode FAQ - Basic questions, Unicode FAQ - UTF-8, UTF-16, UTF-32 & BOM, Wikipedia: UTF-8 [1]

Lazarusコンポーネントライブラリのアーキテクチャの要点

LCL(Lazarusコンポーネントライブラリ)は2つの部分からできています。

  1. DelphiのVCLのように、クラス階層を実装していて、ターゲットプラットホームに依存しない部分 
  2. "Interfaces" つまり、それぞれのターゲットのAPIをインターフェースするために実装している部分。

2つの部分の橋渡しの仕組みは、抽象クラスである TWidgetsetにあります。 それぞれのwidgetsetは、TWidgetsetから派生したクラスの中で実装されています。

Gtk1 widgetsetが最も古いものです。このwidgetsetにおいていは文字列のエンコードはLANG環境変数によって決定されます。このエンコードは、通常はisoのシングルバイトであるISO-8859-nが使われています。最近の多くのディストリビューション(たとえば、Mandriva 2007など)は、Gtk1をUTF-8として設定して出荷されています。ところが、LazarusのGtk1インターフェースは、キーボードの扱いでUTF-8を適切に扱っていません。この問題が最近大きくなり、Lazarusに対するクロスプラットホームでのユニコードサポートの要望が日増しにつよくなっています。

Gtk2 widgetsetはUTF-8エンコードでのみ動きます。しかし、インターフェースのキーボードコードはいまだ昔のGtk1のコードをベースとしていて、UTF-8を完全にはサポートしていません。

Win32インターフェースは、ANSI widgetsとして設定されていますので、現在はwin32ではUnicodeを使うことは不可能です。

Qtインターフェースは、UTF-8として準備されています。Qtそのものは、UCS-2をネイティブなエンコードとして採用しています。LazarusのQtインターフェースはUTF-8をUCS-2に変換しています。

Windows CEのみが、文字列のエンコードとしてUCS-2をサポートしています。しかし、Lazarusの現在のWindowsCEインターフェースでは、WindowsAPIに渡す前に、ISOからUCS-2に変換しています。 これは、すべての変換するコードはwinceproc.ppファイルのいくつかの関数に集中しているので、簡単に修正できます。

こちらも参照してください。: Internals of the LCL

win32インターフェースでユニコードを有効にする

ユニコードを有効にしてLCL-Win32をコンパイルする

Windows環境下でLCLのユニコードを有効にするためには、メニューから"Tools" --> "Configure Build Lazarus"を選択します。 そこで、"Options"フィールドに-dWindowsUnicodeSupportを入れます。 LCLにのみ、Clean+Buildを指定します。そのほかの全てのターゲットにNONEを選択します。 target widgetsetにwin32を指定します。Buildをクリックします。

これで、あなたのすでにあるアプリケーションをUnicodeモードを有効にして再コンパイルできます。 注意:現在の時点では、いくつかのパーツでしか本当にユニコードは有効になっていません。そして、ユニコードが有効になるそれらのパーツでも、バグがあるかもしれません。

方針

まず最初に、最も重要なこととして、Win32インターフェースのすべてのユニコードパッチは、これまでのANSIインターフェースを壊してしまわないように、IFDEF WindowsUnicodeSupportによって囲まれていなければなりません。これらの作業が安定してきてから、すべてのifdefが取り除かれて、ユニコード部分だけが残るようになります。この時点で、すべての既存のANSI文字を使うプログラムが、Unicodeへ移行できるようになるでしょう。

Win9xでのWindowsプラットホームは、ISOコードページ標準でなりたっており、Unicodeは部分的なサポートしかありません。WinNTとWindowsCEを起源とするWindowsプラットホームは、完全にUnicodeをサポートしています。Win9xとNTには、古いANSI文字を引数にとる*Aという関数と、Unicodeワイド文字列(つまり、UTF-16でエンコードされた文字列)を引数にとる*Wという関数の、2つの同じ機能をもったAPI関数を提供しています。Windows CEでは、ワイドAPI関数しか使いません。

Windows 9xに存在するワイド文字列関数

いくつかのWide系API関数はWindows9xにも存在します。ここに、そのような関数のリストを示します。: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mslu/winprog/other_existing_unicode_support.asp

変換例:

  GetTextExtentPoint32(hdcNewBitmap, LPSTR(ButtonCaption),
Length(ButtonCaption), TextSize);

これは、次のようにします。

var
  WideCaption: WideString;

  ....

  {$ifdef WindowsUnicodeSupport}
    WideCaption := Utf8Decode(ButtonCaption);
    GetTextExtentPoint32W(hdcNewBitmap, PWideChar(WideCaption), Length(WideCaption), TextSize);
  {$else}
    GetTextExtentPoint32(hdcNewBitmap, LPSTR(ButtonCaption), Length(ButtonCaption), TextSize);
  {$endif}
end;

AnsiとWideのバージョンが必要な関数

最初の変換例:

function TGDIWindow.GetTitle: String;
var
 l: Integer;
begin
   l := Windows.GetWindowTextLength(Handle);
   SetLength(Result, l);
   Windows.GetWindowText(Handle, @Result[1], l);
end;

これは、次のようにします。

function TGDIWindow.GetTitle: String;
var
 l: Integer;
 AnsiBuffer: string;
 WideBuffer: WideString;
begin

{$ifdef WindowsUnicodeSupport}

 if UnicodeEnabledOS then
 begin
   l := Windows.GetWindowTextLengthW(Handle);
   SetLength(WideBuffer, l);
   l := Windows.GetWindowTextW(Handle, @WideBuffer[1], l);
   SetLength(WideBuffer, l);
   Result := Utf8Encode(WideBuffer);
 end
 else
 begin
   l := Windows.GetWindowTextLength(Handle);
   SetLength(AnsiBuffer, l);
   l := Windows.GetWindowText(Handle, @AnsiBuffer[1], l);
   SetLength(AnsiBuffer, l);
   Result := AnsiToUtf8(AnsiBuffer);
 end;

{$else}

   l := Windows.GetWindowTextLength(Handle);
   SetLength(Result, l);
   Windows.GetWindowText(Handle, @Result[1], l);

{$endif}

end;

ロードマップ

下記は、チェックすべきユニットのリストです。

  • "win32callback.inc"
  • "win32def.pp"
  • "win32int.pp"
  • "win32lclintf.inc"
  • "win32lclintfh.inc"
  • "win32listsl.inc"
  • "win32listslh.inc"
  • "win32memostrings.inc"
  • "win32object.inc"
  • "win32proc.pp"
  • "win32winapi.inc"
  • "win32winapih.inc"
  • "win32wsactnlist.pp"
  • "win32wsarrow.pp"
  • "win32wsbuttons.pp"
  • "win32wscalendar.pp"
  • "win32wschecklst.pp"
  • "win32wsclistbox.pp"
  • "win32wscomctrls.pp"
  • "win32wscontrols.pp"
  • "win32wscustomlistview.inc"
  • "win32wsdbctrls.pp"
  • "win32wsdbgrids.pp"
  • "win32wsdialogs.pp"
  • "win32wsdirsel.pp"
  • "win32wseditbtn.pp"
  • "win32wsextctrls.pp"
  • "win32wsextdlgs.pp"
  • "win32wsfilectrl.pp"
  • "win32wsforms.pp"
  • "win32wsgrids.pp"
  • "win32wsimglist.pp"
  • "win32wsmaskedit.pp"
  • "win32wsmenus.pp"
  • "win32wspairsplitter.pp"
  • "win32wsspin.pp"
  • "win32wsstdctrls.pp"
  • "win32wstoolwin.pp"
  • "winext.pas"