Difference between revisions of "Lazarus For Delphi Users/ja"

From Lazarus wiki
Jump to navigationJump to search
m
m (Fixed syntax highlighting; deleted category included in page template)
 
(24 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 
{{Lazarus For Delphi Users}}
 
{{Lazarus For Delphi Users}}
 +
 +
{{Japanese Menu}}
  
 
この記事は、Lazarusに興味があり、すでにDelphiは知っている、という人々向けのものです。
 
この記事は、Lazarusに興味があり、すでにDelphiは知っている、という人々向けのものです。
 
この二つの違いについて記述しています。
 
この二つの違いについて記述しています。
  
This writeup is for people who are interested in Lazarus and already know Delphi. It describes the differences between the two.
+
==DelphiからLazarusへ==
  
==DelphiからLazarusへ==
+
Lazarusは Delphiと同じく、RAD(Rapid Application Development、手早くアプリケーションを開発できる)ツールの一つです。ビジュアルなコンポーネントライブラリと、IDEがあります。Lazarusのコンポーネントライブラリ(LCL)はDelphiのVCLととても似ています。ほとんどのユニットと、クラスと、プロパティは、同じ名前と機能をもっています。これは、移植を簡単にします。しかし、Lazarusは'オープンソースのDelphiクローン'ではありません。ですから、100%の互換性を期待しないでください。
  
Lazarusは Delphiのような、高速なアプリケーション開発ツールです。すなわち、ビジュアルなコンポーネントライブラリと、IDEがあります。Lazarusのコンポーネントライブラリ(LCL)はDelphiのVCLととても似ています。
+
===最大の相違点は?===
ほとんどのユニットと、クラスと、プロパティは、同じ名前と、機能をもっています。これは、移植を簡単にします。しかし、Lazarusは'オープンソースのDelphiクローン'ではありません。ですから、100%の互換性を期待しないでください。
 
  
Lazarus is an Rapid Application Development (RAD) tool like Delphi. That means it comes with a visual component library and an IDE. The lazarus component library (LCL) is very similar to Delphi's VCL. Most units, classes and properties have the same name and functionality. This makes porting easy. But Lazarus is *not* an 'open source Delphi clone'. So don't expect 100% compatibility.
+
Lazarusは完全にオープンソースで、プラットホームに対し独立しており、強力な[[Free Pascal]]コンパイラ(FPC)を使っています。FPCは15以上のプラットホームで動作します。しかし、すべてのパッケージやライブラリが移植されているわけではありません。ですから、Lazarusは現在のところLinux,FreeBSD,MaxOSX、そしてWin32上で動作します。(訳注:いくつかのPDAでも暫定的な動作はします。日本語に関する処理の改善に、これから皆さんの力を必要としています。)
  
===最大の相違点は?===
+
'''Lazarusは、この文章がまたそうであるように、常に未完です。私たちはいつでも、新しい開発者、パッケージ管理者、移植者、ドキュメントの執筆者を募っています。'''
  
Lazarusは完全にオープンソースで、プラットホームに対し独立しており、強力な[[Free Pascal]]コンパイラ(FPC)を使っています。FPCは15以上のプラットホームで動作します。
+
=== Delphi のプロジェクトを Lazarus 用に変換するためにまず必要なこと ===
しかし、すべてのパッケージやライブラリが移植されているわけではありません。ですから、Lazarusは現在のところLinux,FreeBSD,MaxOSX、そしてWin32上で動作します。
+
Lazarus を起動し、 '''Tools''' メニューから '''Convert Delphi Project to Lazarus Project''' を選んで下さい。これで全てが解決する訳ではありませんが、大変役立つはずです。Lazarus IDE の変換ツールは一般に一方通行であり、逆の変換はできないことに注意して下さい。プロジェクトを Delphi でも Lazarus でもコンパイルできるように Delphi との互換性を維持する必要がある場合は、Lazarus IDEではなく [http://wiki.lazarus.freepascal.org/XDev_Toolkit XDev Toolkit] の利用を考えて下さい。
(訳注:いくつかのPDAでも暫定的な動作はします。日本語に関する処理の改善に、これから皆さんの力を必要としています。)
 
  
'''Lazarusはこの文章のように終わってはいません。私たちはいつでも、新しい開発者、パッケージ管理者、移植者、ドキュメントの執筆者を募っています。'''
+
=== ユニコードのサポート ===
  
Lazarus is completely open source, is written platform independent and uses the mighty [[Free Pascal]] compiler (FPC). FPC runs on more than 15 platforms. But not all packages and libs are ported, so Lazarus currently runs on Linux, FreeBSD, MacOSX and Win32.
+
2007バージョンまでの Delphi はユニコードをサポートせず、Windows が利用していた ANSI エンコーディングを採用していました。2008バージョン以降の Delphi はユニコードをサポートするようになり、UTF-16 を用いて文字列をエンコードしています。
  
''' Lazarus is not complete, as is this text. We are always searching for new developers, packagers, porters, documentation writers, ... . '''
+
一方、Lazarus は UTF-8 を用いたユニコードサポートを始めました。詳しくは [[LCL Unicode Support]] を御読みください。.
  
 
==Delphi IDE から Lazarus IDE へ==
 
==Delphi IDE から Lazarus IDE へ==
 
===プロジェクト===
 
===プロジェクト===
Delphiアプリケーションのメインのファイルは .dprファイルです。Lazarusにおいては、.lpiファイルです。(=Lazarus Project Information)  
+
Delphiアプリケーションのメインのファイルは .dprファイルです。Lazarusにおいては、.lpiファイルです(=Lazarus Project Information)
.dprファイルはメインのソースプログラムであり、DelphiのIDEはコンパイラスイッチやユニットなどの情報の一部を入れます。(訳注:すべてではない。オプションファイルなどがある)Lazarusのアプリケーションもメインのソースファイルをlprファイルに入れます。しかし、そのほかのすべての情報をも入れます。ですから、.lpiファイルがとても重要です。
+
.dprファイルはメインのソースプログラムであり、DelphiのIDEはコンパイラスイッチやユニットなどの情報の一部を入れます(訳注:すべてではない。オプションファイルなどがある)。Lazarusのアプリケーションもメインのソースファイルを.lprファイルに入れます。しかし、そのほかのすべての情報をも入れます。ですから、.lpiファイルはとても重要です。
 
 
The main file of a Delphi application is the .dpr file. The main file of a Lazarus project is the .lpi file (Lazarus Project Information). A .dpr file is the program main source and the Delphi IDE stores some information about the compiler switches and units. A Lazarus application also has a .lpr file, which is also the main source file. But all other information is stored in the .lpi file. So, the important file is the .lpi file.
 
 
 
  
 
例:
 
例:
Delphiはユニットへのパスを.dprファイルに入れます。たとえば、unit1 in 'path/Unit1.pas'というふうにいれますね。このinでパスを指定する方法はDelphi独特であり、Lazarus IDEは読むことができないので、こういう方法をつかわないでください。かわりに、コンパイラオプションで、ユニットパスを指定してください。
+
Delphiはユニットへのパスを.dprファイルに入れます。たとえば、unit1 in 'path/Unit1.pas'というふうにいれます。このinでパスを指定する方法はDelphi独特であり(Pascalの文法ではないので)、Lazarus IDEは読むことができないので、こういう方法をつかわないでください。かわりに、コンパイラオプションで、ユニットパスを指定してください。
  
Delphiはコンパイラオプションを.dprファイルに埋め込みます。たとえば、{$APPTYPE CONSOLE}.というふうにいれますね。Lazarus IDEでは、これらは無視されますので、使わないで下さい。かわりに、コンパイラオプションを使ってください。
+
Delphiはコンパイラオプションを.dprファイルに埋め込みます。たとえば、{$APPTYPE CONSOLE}.というふうにいれます。Lazarus IDEでは、これらは無視されますので、使わないで下さい。かわりに、コンパイラオプションを使ってください。
  
 
(訳注:DelphiのdprファイルはPascalの仕様+独自の部分が結構多いですが、Free Pascal Compiler上のLazarusとしては、Free Pascalに特殊な言語拡張をなるべく行わず、純粋にFree Pascal上に実現できるような方法がとられています。Delphiのようにコンパイラオプションを至る所に定義できるのは、便利でもある一方、スキャンしていかないと、有効か無効かが分からず、バグや全体のみとおしが悪くなる両刃の剣といえますので、訳者は良い仕様だと思います。)
 
(訳注:DelphiのdprファイルはPascalの仕様+独自の部分が結構多いですが、Free Pascal Compiler上のLazarusとしては、Free Pascalに特殊な言語拡張をなるべく行わず、純粋にFree Pascal上に実現できるような方法がとられています。Delphiのようにコンパイラオプションを至る所に定義できるのは、便利でもある一方、スキャンしていかないと、有効か無効かが分からず、バグや全体のみとおしが悪くなる両刃の剣といえますので、訳者は良い仕様だと思います。)
  
For example:
 
 
Delphi stores the paths of the units in the .dpr file. For instance: unit1 in 'path/Unit1.pas'. These 'in' paths are Delphi specific and are not read by the Lazarus IDE. Don't use them. Use instead the compiler options unit paths.
 
 
Delphi stores compiler options in the .dpr file. For instance {$APPTYPE CONSOLE}. These are ignored by the Lazarus IDE. Don't use them. Use instead the compiler options.
 
  
ひとつ重要なルールがあります。それは、''常に''プロジェクトが存在するということです。(訳注:IDE上に?)
+
ひとつ重要なルールがあります。それは、''常に''プロジェクトは存在するということです(訳注:IDEが起動している最中に、ということでしょう)。
 
現在のプロジェクトを"close"する方法は、lazarusを終了するか、他のプロジェクトを開くしかありません。
 
現在のプロジェクトを"close"する方法は、lazarusを終了するか、他のプロジェクトを開くしかありません。
これは、lazarusのプロジェクトはセッションとしての役割があるからです。これは、現在のエディタの設定が、.lpiファイルに記録され、そのプロジェクトを開いたときに再開できるようになっています。たとえば、あなたがアプリケーションをデバッグしていて、多くのブレークポイントやブックマークを開いていたとしましょう。あなたは、いつでもプロジェクトを保存することができ、lazarusを終了したり、他のプロジェクトを開くことができます。あなたは、そのデバッグ中のプロジェクトを開くと、(たとえ他のコンピュータで開いたとしても)ブレークポイント、ブックマーク、開いていたファイル、カーソル位置、ジャンプヒストリ、などといったものが、復元できます。
+
これは、lazarusのプロジェクトはセッションとしての役割があるからです。これは、現在のエディタの設定が、.lpiファイルに記録され、そのプロジェクトを開いたときに再開できるようになっています。たとえば、あなたがアプリケーションをデバッグしていて、多くのブレークポイントやブックマークを開いていたとしましょう。あなたは、いつでもプロジェクトを保存することができ、lazarusを終了したり、他のプロジェクトを開くことができます。その、デバッグ中に保存したプロジェクトを開くと(たとえ他のコンピュータで開いたとしても)、ブレークポイント、ブックマーク、開いていたファイル、カーソル位置、ジャンプヒストリ、などといったものが、復元できます。
 
 
One important rule: There is ''always'' a project.
 
The only way to "close" a project is to exit lazarus or open another project. This is because a lazarus project is also a "session". This means, the current editor settings are also stored in the .lpi file and are restored when you reopen the project. For example: You are debugging an application, set a lot of breakpoints and bookmarks. You can save the project at any time, close lazarus or open another project. When you reopen the project, even on another computer, all your breakpoints, bookmarks, open files, cursor positions, jump history, ... are restored.
 
 
 
  
 
===ソースエディタ===
 
===ソースエディタ===
Line 61: Line 49:
 
これは、完璧に信頼できるものではないかもしれませんが、よく役に立ってます。新しいコードが挿入されると、IDEは発見的な方法を使ってコメントとコードを結び付けます。たとえば、"c: char; // comment"という行は分割されることはありません。
 
これは、完璧に信頼できるものではないかもしれませんが、よく役に立ってます。新しいコードが挿入されると、IDEは発見的な方法を使ってコメントとコードを結び付けます。たとえば、"c: char; // comment"という行は分割されることはありません。
  
Nearly all keys and short cuts can be defined in environment->editor options->key mappings
+
Delphiの"コード補完"(Ctrl+Space)機能は、Lazarusでは、"Identifier Completion"と呼ばれます。Lazarusにおいて、コード補完は、"自動的なクラス補完"(Delphiとおなじです)、"ローカル変数補完"、"イベント割り当て補完"のあわせた機能です。これらのすべては、Ctrl+Shift+Cで呼び出され、IDEは、カーソルの位置から、何をなすべきか決定します。
 
 
The Lazarus IDE has a lot of tools for sources. Many of them look and work very similar to Delphi. But there is one important difference: Lazarus does not use the compiler to get code information. It parses the sources directly. This has a lot of important advantages:
 
 
 
The source editor works with "comments". For Delphi the comments in the source are just space between code. No code feature works there and when new code is auto inserted, your comments will travel. Under Lazarus you can do a find declaration even on code in comments. Although this is not completely reliable, it often works. And when new code is inserted, the IDE uses some heuristics to keep comment and code together. For example: It will not split the line "c: char; // comment".
 
 
 
Delphiの"コード補完"(Ctrl+Space)機能は、Lazarusでは、"Identifier Completion"と呼ばれます。Lazarusにおいて、コード補完は、"自動的なクラス補完"(Delphiとおなじです。)、"ローカル変数補完"、"イベント割り当て補完"のあわせた機能です。これらのすべては、Ctrl+Shift+Cで呼び出され、IDEは、カーソルの位置から、何をなすべきか決定します。
 
  
Delphi's "Code Completion" (Ctrl+Space) is called "Identifier Completion" under Lazarus. The Lazarus term "Code Completion" is a feature, combining "Automatic Class Completion" (same as under Delphi), "Local Variable Completion" and "Event Assignment Completion". All of them are invoked by Ctrl+Shift+C and the IDE determines by the cursor position, what is meant.
 
 
 
 
====ローカル変数補完の例====
 
====ローカル変数補完の例====
 
ちょうど新しいメソッドを作り、"i:=3;"という命令を書いたとしましょう。
 
ちょうど新しいメソッドを作り、"i:=3;"という命令を書いたとしましょう。
{| class="code"
+
 
|- class="code"
+
procedure TForm1.DoSomething;
| class="code" |<div class="key">procedure</div> TForm1.DoSomething;
+
begin
<div class="key">begin</div>
+
  i := 3;
  i:= <div class="int" style="inline">3</div>;
+
end;
<div class="key">end</div>;
 
|}
 
  
 
識別子"i"の上にカーソルをおいて、Ctrl+Shift+Cを押すと、次のようになります。
 
識別子"i"の上にカーソルをおいて、Ctrl+Shift+Cを押すと、次のようになります。
{| class="code"
 
|- class="code"
 
| class="code" |<div class="key">procedure</div> TForm1.DoSomething;
 
<div class="key">var</div> i: Integer;
 
<div class="key">begin</div>
 
  i:= <div class="int">3</div>;
 
<div class="key">end</div>;
 
|}
 
  
 +
procedure TForm1.DoSomething;
 +
var
 +
  i: Integer;
 +
begin
 +
  i := 3;
 +
end;
  
 
====イベント割当補完の例 ====
 
====イベント割当補完の例 ====
  
オブジェクトインスペクタの良い機能のひとつは、自動的にメソッドを作ることです。同じ結果をソースエディタでみることが出来ます。
+
オブジェクトインスペクタの良い機能のひとつに、自動的にメソッドを作ること、があります。ソースエディタでやってみてください。
  
 
たとえば:
 
たとえば:
Line 100: Line 76:
 
代入演算子":="の後で、Ctrl+Shift+Cを押してみてください。
 
代入演算子":="の後で、Ctrl+Shift+Cを押してみてください。
  
A nice feature of the object inspector is to auto create methods. The same you can get in the source editor.<br>
+
==== 手続呼出補完の例 ====
For example:
+
今 "DoSomething(Width);" という文を書き終えた所だとします:
: Button1.OnClick:=
+
<syntaxhighlight lang=pascal>
Position the cursor behind the assign operator ":=" and press Ctrl+Shift+C.
+
procedure SomeProcedure;
 
+
var
====語彙補完 Ctrl+W====
+
  Width: integer;
識別子補完と似ていますが、パスカルの識別子に対してではなく、すべての語彙に対して補完します。あなたが開いているすべてのファイルの中から、あなたがタイプし始めた文字が同じものの語彙を選択することができます。
+
begin
 +
  Width:=3;
 +
  DoSomething(Width);
 +
end;
 +
</syntaxhighlight>
 +
 
 +
識別子 "DoSomething" の上にカーソルを置いて、Ctrl+Shift+C を押すと、こうなります:
  
It works similar to the "Identifier Completion", but it does not work on pascal identifiers, but on all words. It lets you choose of all words in all open files beginning with the same letters.
+
<syntaxhighlight lang=pascal>
 +
procedure DoSomething(aWidth: LongInt);
 +
begin
  
====インクルードファイルのサポート====
+
end;
Delphiではサポートしていませんし、多分、みなさんは多くのインクルードファイルをいまだ作っていないかもしれませんが、インクルードファイルには、大きな利点があります。それは、IFDEFでソースコードを汚さずに、プラットホーム独立なコードを書けるということです。
 
たとえば、メソッドジャンプ、クラス補完、宣言を見つける、など、すべての機能は、インクルードファイルに対しても働きます。
 
  
それらは、コーディングにいろんな機能のオプションがあります。
+
procedure SomeProcedure;
 +
var
 +
  Width: integer;
 +
begin
 +
  Width:=3;
 +
  DoSomething(Width);
 +
end;
 +
</syntaxhighlight>
  
Delphi didn't support it, and so you probably didn't create many include files yet. But include files have a big advantage: They make it possible writing platform (in)dependent code without messing your code with IFDEFs.
+
====語彙補完 Ctrl+W====
For example: Method jumping, Class Completion, find declaration, .. all work with include files.
+
識別子補完と似ていますが、パスカルの識別子に対してではなく、すべての語彙に対して補完します。あなたが開いているすべてのファイルの中から、あなたがタイプし始めた文字が同じものの語彙をリストアップし、選択できます。
  
There are many options for the code features.
+
====インクルードファイルのサポート====
 +
Delphiではインクルードファイルをサポートしていませんので(訳注:$iがあるので、補完機能が、ということだろう)、多分、みなさんは多くのインクルードファイルを今までに作っていないかもしれません。しかし、インクルードファイルには、大きな利点があります。それは、IFDEFでソースコードを汚さずに、プラットホーム独立なコードを書けるということです。
 +
Lazarusでは、メソッドジャンプ、クラス補完、宣言を見つける、など、すべての機能は、インクルードファイルに対しても働きます。
 +
また、コーディング機能にいろんなオプションがあります。
  
 
===デザイナ===
 
===デザイナ===
Line 126: Line 118:
 
====オブジェクト・インスペクタ====
 
====オブジェクト・インスペクタ====
  
DelphiとLazarusのIDEにおいて、オブジェクトインスペクタはコンポーネントプロパティを編集したり、イベントを設定したりするのに使われます。使い方に、いくつかの小さな違いがあります。
+
DelphiとLazarusのIDEでは、オブジェクトインスペクタはコンポーネントプロパティを編集したり、イベントを設定したりするのに使われます。使い方に、いくつかの小さな違いがあります。
#Delphi5を起動すると、オブジェクトインスペクタのなかで、階層にしたがって伝統的なドロップダウンリストの中でオブジェクトを選択できるオブジェクトツリービューがあります。Lazarusでは、これは、オブジェクトインスペクタの一部にすぎません。デフォルトのドロップダウンリストのかわりに、右クリックで表示される"Show Component Tree"メニューを使うこともできます。
+
#Delphi5を起動すると、オブジェクトインスペクタのなかで、階層にしたがって伝統的なドロップダウンリストでオブジェクトを選択できるオブジェクトツリービューがあります。Lazarusでは、これは、オブジェクトインスペクタの一部にすぎません。デフォルトのドロップダウンリストのかわりに、右クリックで表示される"Show Component Tree"メニューを使うこともできます。
#Delphiでは、空のイベントでダブルクリックすると、自動的にイベントを作成し、ソースエディターがその位置を開きます。Lazarusは右側にボタンがあり、ドロップダウンでこの動作を選択することができます。
+
#Delphiでは、空のイベントでダブルクリックすると、自動的にイベントを作成し、ソースエディターがその位置を開きます。Lazarusは右側にボタンがあり、ドロップダウンでイベントを作成することができます。
 
#Delphiでは、つけられたイベント名は手で消さなくてはなりませんが、Lazarusでは、"(None)"をドロップダウンで選ぶことができます。
 
#Delphiでは、つけられたイベント名は手で消さなくてはなりませんが、Lazarusでは、"(None)"をドロップダウンで選ぶことができます。
#Eventと同じように、booleanのような標準的なプロパティをダブルクリックすることで、値は変化しません。ドロップダウンで選択する必要があります。そして、エディターフォームで結び付けられているものを開くには、editやdrop-downの右側にある'...'ボタンをクリックする必要があります。
+
#Eventと同じように、booleanのような標準的なプロパティをダブルクリックすることでは、値は変化しません。値を変えるには、ドロップダウンで選択する必要があります。そして、エディターフォームで結び付けられているものを開くには、editやdrop-downの右側にある'...'ボタンをクリックする必要があります。
 
 
In the Delphi and Lazarus IDE's the Object Inspector is used to edit component properties and assign events etc. The following are a few minor differences to note in use  :
 
# Starting in Delphi 5 there is an Object Treeview which can be used to navigate and select objects according to hierarchy in addition to the traditional drop down list in the Object Inspector. In Lazarus this is part of the Object Inspector and is used in place of the default drop-down, you can select to use/not use it from the right click menu with "Show Component Tree"
 
# In Delphi double clicking on a blank event will auto create one and open the Source Editor to that position, in Lazarus there is a button to the right of the selected drop-down which performs this action instead.
 
# In Delphi you must manually delete the name of an event in the edit to remove the attatchement, in Lazarus you can drop down and select "(None)".
 
# Similarly to Events, double clicking regular properties such as boolean will not change the value, you must select it from a drop down. And to open those with an assigned editor form, you must click the '...' button to the right of the edit/drop-down
 
  
 
====パッケージ====
 
====パッケージ====
 
LazarusはDelphiのパッケージをインストールして使うことはできますか?
 
LazarusはDelphiのパッケージをインストールして使うことはできますか?
  
いいえ、なぜなら、それには、Delphiのコンパイラマジックが必要だからです。
+
いいえ、なぜなら、それには、Delphiのコンパイラマジック(訳注:Pascalではない部分の特殊な文法)が必要だからです。
  
 
私たちは、Lazarus向けに特別にパッケージを作りたいのですが?
 
私たちは、Lazarus向けに特別にパッケージを作りたいのですが?
Line 151: Line 137:
  
  
Can Lazarus install and use Delphi Packages?
 
  
No, because they require Delphi compiler magic.
+
===VCL から LCL ===
 
 
Do we need ones specially made for lazarus?
 
 
 
Yes.
 
Create a new package, save it in the package source directory (normally same
 
directory of the .dpk file), add the LCL as required package and finally add
 
the .pas files.
 
You can install it, or use it in your projects now.
 
There are some differences between Lazarus and Delphi packages, so please
 
read
 
 
 
- see docs/Packages.txt in the lazarus sources.
 
 
 
===VCL -> LCL===
 
 
VCLとLCLは、ともに、高速なアプリケーション開発向けの、オブジェクト指向の階層的なコンポーネントのライブラリです。しかし、それらは同じではありません。
 
VCLとLCLは、ともに、高速なアプリケーション開発向けの、オブジェクト指向の階層的なコンポーネントのライブラリです。しかし、それらは同じではありません。
 
たとえば、VCLは多くの非ビジュアルなコンポーネントを含みます。一方、LCLは、[[Free Pascal]]によって、多くの「ビジュアルでない」コンポーネント(データベースアクセスなど)が提供されていますので、ビジュアルなコンポーネントのみ、を提供しようとしています。
 
たとえば、VCLは多くの非ビジュアルなコンポーネントを含みます。一方、LCLは、[[Free Pascal]]によって、多くの「ビジュアルでない」コンポーネント(データベースアクセスなど)が提供されていますので、ビジュアルなコンポーネントのみ、を提供しようとしています。
(訳注:データベースの表示については、ビジュアルである。そのなかで使われるデータベースアクセス自体はLCLコンポーネント内に統合される)
+
(訳注:データベースの表示については、ビジュアルである。そのなかで使われるデータベースアクセス自体はLCLコンポーネント内に統合されていると思われる)
  
  
While the VCL and the LCL both serve much of the same purpose - of an Object Oriented Component Hierarchy especially geared toward rapid application development, they are not identical. For instance while the VCL provides many non-visual components, the LCL tries to only provide visual, while most non-visual components (such as db access) are provided by the FCL, included with [[Free Pascal]] .
+
加えていうと、VCL等にある多くのコントロールが、LCLには存在しないかもしれませんし、同じようなコントロールが両方に存在する場合でも、それらはクローンではありません。
 +
ですから、もし移植をするなら、アプリケーション、コンポーネント、およびコントロールのそれぞれで変更が必要です。
  
 +
次のことはDelphiユーザのために、DelphiとLazarusの主要な違いや、互換性のない所を、包み隠さずに明らかにしようとするものです。これは、主にD4でのVCL(D5,D6,D7も同様です)と、現在のCVSに、あるがままのLCLの違いをカバーしました。あなたがいつも使っているDelphiやLCLのバージョンに完全に一致しないかもしれません。もし、これらの記述が正確でないとすれば、他の皆さんの理解のために、ご自由に記述を加えたり、変更してください。
  
加えていうと、多くのコントロールがVCLやその類にあっても、LCLに存在しないかもしれません。同じようなコントロールが両方に存在する場合でも、それらはクローンではありません。
+
====TControl.Font/TControl.ParentFontについて====
ですから、もし移植をするなら、アプリケーション、コンポーネント、およびコントロールで変更が必要です。
 
  
Additionally many controls may not exist in the LCL that are in the VCL, or vica versa, or even when controls do exist in both, they are not clones, and changes must be made in applications, components and controls if porting.
+
VCLでは、コントロールにフォントのプロパティとして、ボールドやイタリック、特定のフォント名と等を使用し、通常はこの値がいつも子へと引き継がれていきます。
 +
さらに、コントロールがいつもParentのフォントを確実にする継承するために、TControl.ParentFontプロパティを提供しています。
 +
OSにウインドウの見え方の設定があるのですが、コントロールのプロパティが常時優先されるということを暗に決めてつけてしまっています。
  
次のことはDelphiユーザのために、DelphiとLazarusの主要な違いや、互換性のない所を、公正に明らかにしようとするものです。これは、主にD4でのVCL(しかし、同時にD5,D6,D7も同様です)と、現在のCVSにあるままの現在のLCLの違いをカバーします。ですから、あなたがいつも使っているDelphiやLCLのバージョンに完全に一致しないかもしれません。もし、これらの記述が正確でないとすれば、他の皆さんの理解のために、ご自由に記述を加えたり、変更してください。
+
(訳注:Windowsで画面で大きい文字などが選択できるが、他のデスクトップではもっと多くのことが指定できるものがあるので、Delphiにおいてもシステムフォントを取得することが望ましい、とされる場合もあるが、きっちりデザインが難しくなる。)
  
The following is an attempt to provide fairly complete descriptions of major differences or incompatiblities between the two for the Delphi user. It covers differences primarily with the VCL of D4 especially, though at times D5, D6, or D7 as well; and with the current LCL, as is in CVS. As such it may not always be accurate to the version of Delphi you are used to, or completely match the current LCL you have. If you see inacuracies between the following and the LCL as in CVS, or your Delphi feel free to append and modify so as to keep this as comprehensive as possible for all people.
+
このフォントについての機能、解釈はLCLでは、異なっています。 現実にクロスプラットフォーム/クロスインタフェースであるLCLは、バランスのとれた手法を好んで採用しようとしています。LCLは、いつでも、どんなウィジェットでのネイティブのDesktop/ツールキットのApearance、Theme設定も使用しようとします。
 +
例えば、テーマが、ボタンのための特定の字体を供給するGTKインタフェース、およびgtkを使用することがありますが、LCLボタンはいつもこのテーマに沿った字体を使用します。
  
====TControl.Font/TControl.ParentFontについて====
+
このことは、ほとんどのLCLコントロールはVCLで当たり前になっている、設計上のフォントなどの管理機能は持っていない、ということです。
 +
しかし、もし、この仕様を変更したければ、使用されるインターフェースにかかわらず、この様に統一的に割り当てられたインタフェースに代わり、Canvasに独自で描画するカスタムコントロールを使うことができます。
  
 +
例えば太字や、特別な色の字体のLabelが必要な場合、代わりにTStaticTextを使用しなければなりません。
 +
なぜなら、TLabelは特定のコントロールのインタフェースであり、すべてのインタフェースのネイティブなバージョンを供給するのであるならば、その大部分は、すべての環境が考慮されないかもしれない、デフォルトの設定が利用されるでしょう。
  
 +
====ドラッグとドッキングの制御====
 +
VCLでは、実行中に、例えば1個のパネルからコントロールをドラッグして、別のパネルにドッキングできるように、ほとんどのTWinControlからの派生コントロールは、ドラッグ、ドッキングを制御する機能が組み込まれています。
  
In the VCL it is quite common and normal to use a specific font name and font properties such as bold and italics for controls, and expect this value to always be followed. Further is provided the TControl.ParentFont property which ensures that a control will always follow its parent's font. Again the implicit assumption being that these values will always be followed, even regardless of Windows Apearance Settings.
+
この機能はLCLでは、現在、未完成であり、実装されていません。現在、設計の初期段階です。このタイプのふるまいが、同じような方法で、同等のレベルの互換性を維持するように、最終的には、サポートしてくれると思います。
  
This is not always true in the LCL, nor can it be. The LCL being cross-platform/cross-interface in nature prefers to take a balanced aproach, and instead will always try to use native Desktop/Toolkit Apearance or Theme settings on any widgets. For example if using a GTK interface, and the gtk theme supplies a specific font for buttons, then LCL buttons will always try to use this font.
+
これは、現在、どんなControlも以下のTControlの機能、プロシージャ、プロパティを継承していない、使っていない、ということを意味します。
 +
<syntaxhighlight lang=pascal>
 +
Protected
 +
  function GetDockEdge(MousePos: TPoint): TAlign;
 +
  function GetDragImages: TDragImageList;
 +
  function GetFloating: Boolean;
 +
  function GetFloatingDockSiteClass: TWinControlClass;
 +
  procedure DoEndDrag(Target:TObject); X, Y: Integer);
 +
  procedure DockTrackNoTarget(Source: TDragDockObject; X, Y: Integer);
 +
  procedure DoEndDock(Target: TObject; X, Y: Integer);
 +
  procedure DoDock(NewDockSite: TWinControl; var ARect: TRect);
 +
  procedure DoStartDock(var DragObject: TDragObject);
 +
  procedure DragCanceled;
 +
  procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
 +
                    var Accept: Boolean);
 +
  procedure DoEndDrag(Target: TObject; X, Y: Integer);
 +
  procedure DoStartDrag(var DragObject: TDragObject);
 +
  procedure DrawDragDockImage(DragDockObject: TDragDockObject);
 +
  procedure EraseDragDockImage(DragDockObject: TDragDockObject);
 +
  procedure PositionDockRect(DragDockObject: TDragDockObject);
 +
  procedure SetDragMode(Value: TDragMode);
 +
  property DragKind: TDragKind;
 +
  property DragCursor: TCursor;
 +
  property DragMode: TDragMode;
 +
  property OnDragDrop: TDragDropEvent;
 +
  property OnDragOver: TDragOverEvent;
 +
  property OnEndDock: TEndDragEvent;
 +
  property OnEndDrag: TEndDragEvent;
 +
  property OnStartDock: TStartDockEvent;
 +
  property OnStartDrag: TStartDragEvent;
 +
public
 +
  function Dragging: Boolean;
 +
  function ManualDock(NewDockSite: TWinControl; DropControl: TControl;
 +
                    ControlSide: TAlign): Boolean;
 +
  function ManualFloat(ScreenPos: TRect): Boolean;
 +
  function ReplaceDockedControl(Control: TControl; NewDockSite: TWinControl;
 +
                      DropControl: TControl; ControlSide: TAlign): Boolean;
 +
  procedure BeginDrag(Immediate: Boolean; Threshold: Integer);
 +
  procedure Dock(NewDockSite: TWinControl; ARect: TRect);
 +
  procedure DragDrop(Source: TObject; X, Y: Integer);
 +
  procedure EndDrag(Drop: Boolean);
 +
  property DockOrientation: TDockOrientation;
 +
  property Floating: Boolean;
 +
  property FloatingDockSiteClass: TWinControlClass;
 +
  property HostDockSite: TWinControl;
 +
  property LRDockWidth: Integer;
 +
  property TBDockHeight: Integer;
 +
  property UndockHeight: Integer;
 +
  property UndockWidth: Integer;
 +
</syntaxhighlight>
  
This means that most LCL controls do not have the same level of design control that is often expected in the VCL, rather only those custom controls which are Canvas drawn instead of interface allocated can consistantly be modified in this manner regardless of the Interface used.
+
that the following classes do not exist/are unusable -
  
If for instance a Label with a bold/special color font is required, a TStaticText must be used instead, as TLabel is an interface specific control and all interfaces will supply a native version, and most will have default settings which will be used regardless.
+
<syntaxhighlight lang=pascal>
 +
TDragImageList = class(TCustomImageList)
 +
TDockZone = class
 +
TDockTree = class(TInterfacedObject, IDockManager)
 +
TDragObject = class(TObject)
 +
TBaseDragControlObject = class(TDragObject)
 +
TDragControlObject = class(TBaseDragControlObject)
 +
TDragDockObject = class(TBaseDragControlObject)
 +
</syntaxhighlight>
  
====Control Dragging/Docking====
+
下記の関数も、利用できないか、互換性がありません。
In the VCL most (Win)Controls implement methods and callback functions for handling dragging and docking of controls, eg. dragging a control from one panel, and docking it onto another panel at run time.
 
  
This functionality is currently unimplimented/unfinished in the LCL, though it is currently in the initial stages of planning, and should eventually support some level of compatibility for this type of behaviour, if not in the exact same manner.
+
<syntaxhighlight lang=pascal>
 +
function FindDragTarget(const Pos: TPoint;
 +
                        AllowDisabled: Boolean) : TControl;
 +
procedure CancelDrag;
 +
function IsDragObject(sender: TObject): Boolean;
 +
</syntaxhighlight>
  
This currently means that no Control will inherit/use the following TControl functions, procedures, properties, or events  -
+
====TEdit、および、TCustomEditについて====
{| class="code"
 
|- class="code"
 
| class="code" |<div class="key">Protected</div>
 
  <div class="key">function</div> GetDockEdge(MousePos: TPoint): TAlign;
 
  <div class="key">function</div> GetDragImages: TDragImageList;
 
  <div class="key">function</div> GetFloating: Boolean;
 
  <div class="key">function</div> GetFloatingDockSiteClass: TWinControlClass;
 
  <div class="key">procedure</div> DoEndDrag(Target:TObject); X, Y: Integer);
 
  <div class="key">procedure</div> DockTrackNoTarget(Source: TDragDockObject; X, Y: Integer);
 
  <div class="key">procedure</div> DoEndDock(Target: TObject; X, Y: Integer);
 
  <div class="key">procedure</div> DoDock(NewDockSite: TWinControl; <div class="key">var</div> ARect: TRect);
 
  <div class="key">procedure</div> DoStartDock(<div class="key">var</div> DragObject: TDragObject);
 
  <div class="key">procedure</div> DragCanceled;
 
  <div class="key">procedure</div> DragOver(Source: TObject; X, Y: Integer; State: TDragState;
 
                    <div class="key">var</div> Accept: Boolean);
 
  <div class="key">procedure</div> DoEndDrag(Target: TObject; X, Y: Integer);
 
  <div class="key">procedure</div> DoStartDrag(<div class="key">var</div> DragObject: TDragObject);
 
  <div class="key">procedure</div> DrawDragDockImage(DragDockObject: TDragDockObject);
 
  <div class="key">procedure</div> EraseDragDockImage(DragDockObject: TDragDockObject);
 
  <div class="key">procedure</div> PositionDockRect(DragDockObject: TDragDockObject);
 
  <div class="key">procedure</div> SetDragMode(Value: TDragMode);
 
  <div class="key">property</div> DragKind: TDragKind;
 
  <div class="key">property</div> DragCursor: TCursor;
 
  <div class="key">property</div> DragMode: TDragMode;
 
  <div class="key">property</div> OnDragDrop: TDragDropEvent;
 
  <div class="key">property</div> OnDragOver: TDragOverEvent;
 
  <div class="key">property</div> OnEndDock: TEndDragEvent;
 
  <div class="key">property</div> OnEndDrag: TEndDragEvent;
 
  <div class="key">property</div> OnStartDock: TStartDockEvent;
 
  <div class="key">property</div> OnStartDrag: TStartDragEvent;
 
<div class="key">public</div>
 
  <div class="key">function</div> Dragging: Boolean;
 
  <div class="key">function</div> ManualDock(NewDockSite: TWinControl; DropControl: TControl;
 
                    <div class="key"> </div>ControlSide: TAlign): Boolean;
 
  <div class="key">function</div> ManualFloat(ScreenPos: TRect): Boolean;
 
  <div class="key">function</div> ReplaceDockedControl(Control: TControl; NewDockSite: TWinControl;
 
                    <div class="key"> </div>DropControl: TControl; ControlSide: TAlign): Boolean;
 
  <div class="key">procedure</div> BeginDrag(Immediate: Boolean; Threshold: Integer);
 
  <div class="key">procedure</div> Dock(NewDockSite: TWinControl; ARect: TRect);
 
  <div class="key">procedure</div> DragDrop(Source: TObject; X, Y: Integer);
 
  <div class="key">procedure</div> EndDrag(Drop: Boolean);
 
  <div class="key">property</div> DockOrientation: TDockOrientation;
 
  <div class="key">property</div> Floating: Boolean;
 
  <div class="key">property</div> FloatingDockSiteClass: TWinControlClass;
 
  <div class="key">property</div> HostDockSite: TWinControl;
 
  <div class="key">property</div> LRDockWidth: Integer;
 
  <div class="key">property</div> TBDockHeight: Integer;
 
  <div class="key">property</div> UndockHeight: Integer;
 
  <div class="key">property</div> UndockWidth: Integer;
 
|}
 
  
that the following classes do not exist/are unuseable -
+
Editコントロールは、LCLもVCLと同等の機能をもっていますが、移植中に、いくつかの気をつけるべき点があります。
{| class="code"
 
|- class="code"
 
| class="code" | TDragImageList = <div class="key">class</div>(TCustomImageList)
 
TDockZone = <div class="key">class</div>
 
TDockTree = <div class="key">class</div>(TInterfacedObject, IDockManager)
 
TDragObject = <div class="key">class</div>(TObject)
 
TBaseDragControlObject = <div class="key">class</div>(TDragObject)
 
TDragControlObject = <div class="key">class</div>(TBaseDragControlObject)
 
TDragDockObject = <div class="key">class</div>(TBaseDragControlObject)
 
|}
 
and that the following functions are also unuseable/incompatible -
 
{| class="code"
 
|- class="code"
 
| class="code" | <div class="key">function</div> FindDragTarget(<div class="key">const</div> Pos: TPoint;
 
                        <div class="key"> </div>AllowDisabled: Boolean) : TControl;
 
<div class="key">procedure</div> CancelDrag;
 
<div class="key">function</div> IsDragObject(sender: TObject): Boolean;
 
|}
 
  
====TEdit/TCustomEdit====
+
#GUIインターフェースでの制限で、TEdit.PasswordCharはすべてのインタフェースでは、まだ正常に機能しません。入力テキストを隠するために必要とする場合は、代わりに、TCustomEdit.EchoMode emPasswordを使用します。
The Edit controls, while functioning essentialy the same in the LCL as the VCL, do have some issues to be aware of in converting -
+
# ドラッグ、ドッキングイベントはまだ実装されていません。詳しくは、[[#Control Dragging/Docking | Control Dragging/Docking]].
# Due to restrictions in the Interfaces, TEdit.PasswordChar does not work in all interfaces yet(though in time it may), instead TCustomEdit.EchoMode emPassword should be used in the event text needs to be hidden.
+
# フォントプロパティは、GUIの統一性のためにたいてい無視されます。詳しくは、[[#TControl.Font/TControl.ParentFont | TControl.Font/TControl.ParentFont]]
# On Drag/Dock Events are not yet implemented. For more information please see earlier section on [LazarusForDelphiUsers#Control Dragging/Docking|Control Dragging/Docking].
 
# Font Properties are usually ignored for interface consistancy, for detailed explanation as too why please see [[#TControl.Font/TControl.ParentFont | TControl.Font/TControl.ParentFont]]
 
  
 
===(optional) TSplitter -> TPairSplitter===
 
===(optional) TSplitter -> TPairSplitter===
 +
 
'''Please Improve Me'''
 
'''Please Improve Me'''
  
Line 309: Line 281:
  
 
If the splitter and controls are created within an actual function(like form oncreate), conversion shouldn't be too difficult, primarily reorganize the code to create the controls in order of new hierarchy and set the parents of the child controls to split to the left/top and right/bottom portions of the PairSplitter. An example  of the changes being -  
 
If the splitter and controls are created within an actual function(like form oncreate), conversion shouldn't be too difficult, primarily reorganize the code to create the controls in order of new hierarchy and set the parents of the child controls to split to the left/top and right/bottom portions of the PairSplitter. An example  of the changes being -  
 +
 
{| class="code"
 
{| class="code"
 
|-  
 
|-  
| class="header" | VCL || class="header" | LCL
+
| class="header" | '''VCL''' || class="header" | '''LCL'''
 
|- class="code"
 
|- class="code"
| class="code" |<div class="key">var</div>
+
| class="code" |
  BottomPanel: TPanel<div class="symbol">;</div>
+
<syntaxhighlight lang=pascal>
<div></div>
+
var  
  VerticalSplitter: TSplitter<div class="symbol">;</div>
+
  BottomPanel: TPanel;
  LeftPanel: TPanel<div class="symbol">;</div>
+
  VerticalSplitter: TSplitter;
  HorizontalSplitter: TSplitter<div class="symbol">;</div>
+
  LeftPanel: TPanel;
<div></div>
+
  HorizontalSplitter: TSplitter;
  MainPanel: TPanel<div class="symbol">;</div>
+
  MainPanel: TPanel;
  <div class="key">begin</div>
+
 
  BottomPanel:= TPanel.Create(Self)<div class="symbol">;</div>
+
begin
  <div class="key">with</div> (BottomPanel) <div class="key">do</div>
+
  BottomPanel:= TPanel.Create(Self);
  <div class="key">begin</div>
+
  with (BottomPanel) do
    Parent:= Self<div class="symbol">;</div>
+
  begin
    Height:= <div class="int">75</div><div class="symbol">;</div>
+
    Parent:= Self;
    Align:= alBottom<div class="symbol">;</div>
+
    Height:= 75;
  <div class="key">end</div><div class="symbol">;</div>
+
    Align:= alBottom;
<div></div>
+
  end;
  VerticalSplitter:= TSplitter.Create(Self)<div class="symbol">;</div>
+
 
  <div class="key">with</div> (VerticalSplitter) <div class="key">do</div>
+
  VerticalSplitter:= TSplitter.Create(Self);
  <div class="key">begin</div>
+
  with (VerticalSplitter) do
    Parent:= Self<div class="symbol">;</div>
+
  begin
    Align:= alBottom<div class="symbol">;</div>
+
    Parent:= Self;
  <div class="key">end</div><div class="symbol">;</div>
+
    Align:= alBottom;
<div></div>
+
  end;
  HorizontalSplitter:= TSplitter.Create(Self)<div class="symbol">;</div>
+
 
  <div class="key">with</div> (HorizontalSplitter) <div class="key">do</div>
+
  HorizontalSplitter:= TSplitter.Create(Self);
  <div class="key">begin</div>
+
  with (HorizontalSplitter) do
    Parent:= Self<div class="symbol">;</div>
+
  begin
    align:= alLeft<div class="symbol">;</div>
+
    Parent:= Self;
  <div class="key">end</div><div class="symbol">;</div>
+
    align:= alLeft;
<div></div>
+
  end;
  LeftPanel:= TPanel.Create(Self)<div class="symbol">;</div>
+
 
  <div class="key">with</div> (LeftPanel) <div class="key">do</div>
+
  LeftPanel:= TPanel.Create(Self);
  <div class="key">begin</div>
+
  with (LeftPanel) do
    Parent:= Self<div class="symbol">;</div>
+
  begin
    Width:= <div class="int">125</div><div class="symbol">;</div>
+
    Parent:= Self;
    Align:= alLeft<div class="symbol">;</div>
+
    Width:= 125;
  <div class="key">end</div><div class="symbol">;</div>
+
    Align:= alLeft;
<div></div>
+
  end;
  MainPanel:= TPanel.Create(Self)<div class="symbol">;</div>
+
 
  <div class="key">with</div> (MainPanel) <div class="key">do</div>
+
  MainPanel:= TPanel.Create(Self);
  <div class="key">begin</div>
+
  with (MainPanel) do
    Parent:= Self<div class="symbol">;</div>
+
  begin
    Align:= alClient<div class="symbol">;</div>
+
    Parent:= Self;
    Caption:= <div class="str">'Hello'</div><div class="symbol">;</div>
+
    Align:= alClient;
  <div class="key">end</div><div class="symbol">;</div>
+
    Caption:= 'Hello';
<div class="key">end</div>;
+
  end;
| class="code" | <div class="key">var</div>
+
end;
  BottomPanel: TPanel<div class="symbol">;</div>
+
</syntaxhighlight>
<div></div>
+
| class="code" |  
  VerticalSplitter: TPairSplitter<div class="symbol">;</div>
+
<syntaxhighlight lang=pascal>
  LeftPanel: TPanel<div class="symbol">;</div>
+
var
  HorizontalSplitter: TPairSplitter<div class="symbol">;</div>
+
  BottomPanel: TPanel;
<div></div>
+
  VerticalSplitter: TPairSplitter;
  MainPanel: TPanel<div class="symbol">;</div>
+
  LeftPanel: TPanel;
<div class="key">begin</div>
+
  HorizontalSplitter: TPairSplitter;
  VerticalSplitter:= TPairSplitter.Create(Self)<div class="symbol">;</div>
+
  MainPanel: TPanel;
  <div class="key">with</div> (VerticalSplitter) <div class="key">do</div>
+
 
  <div class="key">begin</div>
+
begin
    Parent:= Self<div class="symbol">;</div>
+
  VerticalSplitter:= TPairSplitter.Create(Self);
    Align:= alClient<div class="symbol">;</div>
+
  with (VerticalSplitter) do
    Width:= Self.Width<div class="symbol">;</div>
+
  begin
    Height:= Self.Height<div class="symbol">;</div>
+
    Parent:= Self;
    SplitterType:= pstVertical<div class="symbol">;</div>
+
    Align:= alClient;
    Position:= Height - <div class="int">75</div><div class="symbol">;</div>
+
    Width:= Self.Width;
    Sides[<div class="int">0</div>].Width:= Width<div class="symbol">;</div>
+
    Height:= Self.Height;
    Sides[<div class="int">0</div>].Height:= Position<div class="symbol">;</div>
+
    SplitterType:= pstVertical;
  <div class="key">end</div><div class="symbol">;</div>
+
    Position:= Height - 75;
<div></div>
+
    Sides[0].Width:= Width;
  HorizontalSplitter:= TPairSplitter.Create(Self)<div class="symbol">;</div>
+
    Sides[0].Height:= Position;
  <div class="key">with</div> (HorizontalSplitter) <div class="key">do</div>
+
  end;
  <div class="key">begin</div>
+
 
    Parent:= VerticalSplitter.Sides[<div class="int">0</div>]<div class="symbol">;</div>
+
  HorizontalSplitter:= TPairSplitter.Create(Self);
    Width:= Self.Width<div class="symbol">;</div>
+
  with (HorizontalSplitter) do
    Height:= VerticalSplitter.Position<div class="symbol">;</div>
+
  begin
    align:= alClient<div class="symbol">;</div>
+
    Parent:= VerticalSplitter.Sides[0];
    SplitterType:= pstHorizontal<div class="symbol">;</div>
+
    Width:= Self.Width;
    Position:= <div class="int">125</div><div class="symbol">;</div>
+
    Height:= VerticalSplitter.Position;
  <div class="key">end</div><div class="symbol">;</div>
+
    align:= alClient;
<div></div>
+
    SplitterType:= pstHorizontal;
  LeftPanel:= TPanel.Create(Self)<div class="symbol">;</div>
+
    Position:= 125;
  <div class="key">with</div> (LeftPanel) <div class="key">do</div>
+
  end;
  <div class="key">begin</div>
+
 
    Parent:= HorizontalSplitter.Sides[<div class="int">0</div>]<div class="symbol">;</div>
+
  LeftPanel:= TPanel.Create(Self);
    Align:= alClient<div class="symbol">;</div>
+
  with (LeftPanel) do
  <div class="key">end</div><div class="symbol">;</div>
+
  begin
<div></div>
+
    Parent:= HorizontalSplitter.Sides[0];
  MainPanel:= TPanel.Create(Self)<div class="symbol">;</div>
+
    Align:= alClient;
  <div class="key">with</div> (MainPanel) <div class="key">do</div>
+
  end;
  <div class="key">begin</div>
+
 
    Parent:= HorizontalSplitter.Sides[<div class="int">1</div>]<div class="symbol">;</div>
+
  MainPanel:= TPanel.Create(Self);
    Align:= alClient<div class="symbol">;</div>
+
  with (MainPanel) do
    Caption:= <div class="str">'Hello'</div><div class="symbol">;</div>
+
  begin
  <div class="key">end</div><div class="symbol">;</div>
+
    Parent:= HorizontalSplitter.Sides[1];
<div></div>
+
    Align:= alClient;
  BottomPanel:= TPanel.Create(Self)<div class="symbol">;</div>
+
    Caption:= 'Hello';
  <div class="key">with</div> (BottomPanel) <div class="key">do</div>
+
  end;
  <div class="key">begin</div>
+
 
    Parent:= VerticalSplitter.Sides[<div class="int">1</div>]<div class="symbol">;</div>
+
  BottomPanel:= TPanel.Create(Self);
    Align:= alClient<div class="symbol">;</div>
+
  with (BottomPanel) do
  <div class="key">end</div><div class="symbol">;</div>
+
  begin
<div class="key">end</div><div class="symbol">;</div>
+
    Parent:= VerticalSplitter.Sides[1];
 +
    Align:= alClient;
 +
  end;
 +
end;
 +
</syntaxhighlight>
 
|}
 
|}
  
Line 423: Line 400:
 
{| class="code"
 
{| class="code"
 
|-  
 
|-  
| class="header" | Delphi DFM <div style="font-weight: normal">(extraneous values removed)</div>
+
| class="header" | '''Delphi DFM''' <div style="font-weight: normal">'''(extraneous values removed)'''
| class="header" | Lazarus LFM <div style="font-weight: normal">(most width, height, etc. removed)</div>
+
| class="header" | '''Lazarus LFM''' <div style="font-weight: normal">'''(most width, height, etc. removed)'''
 
|- class="code"
 
|- class="code"
| class="code" |<div class="key">object</div>VerticalSplitter: TSplitter
+
| class="code" |
   Height <div class="symbol">=</div> <div class="int">3</div>
+
<syntaxhighlight lang=pascal>
   Cursor <div class="symbol">=</div> crVSplit
+
object VerticalSplitter: TSplitter
   Align <div class="symbol">=</div> alBottom
+
   Height = 3
<div class="key">end</div>
+
   Cursor = crVSplit
<div class="key">object</div> HorizontalSplitter: TSplitter
+
   Align = alBottom
   Width <div class="symbol">=</div> <div class="int">3</div>
+
end
   Align <div class="symbol">=</div> alLeft
+
object HorizontalSplitter: TSplitter
<div class="key">end</div>
+
   Width = 3
<div class="key">object</div> BottomPanel: TPanel
+
   Align = alLeft
   Height <div class="symbol">=</div> <div class="int">75</div>
+
end
   Align <div class="symbol">=</div> alBottom
+
object BottomPanel: TPanel
<div class="key">end</div>
+
   Height = 75
<div class="key">object</div> LeftPanel: TPanel
+
   Align = alBottom
   Width <div class="symbol">=</div> <div class="int">125</div>
+
end
   Align <div class="symbol">=</div> alLeft
+
object LeftPanel: TPanel
<div class="key">end</div>
+
   Width = 125
<div class="key">object</div> MainPanel: TPanel
+
   Align = alLeft
   Align <div class="symbol">=</div> alClient
+
end
<div class="key">end</div>  
+
object MainPanel: TPanel
| class="code" |<div class="key">object</div> VerticalSplitter: TPairSplitter
+
   Align = alClient
   Align <div class="symbol">=</div> alClient
+
end  
   SplitterType <div class="symbol">=</div> pstVertical
+
</syntaxhighlight>
   Position <div class="symbol">=</div> <div class="int">225</div>
+
| class="code" |
   Height <div class="symbol">=</div> <div class="int">300</div>
+
<syntaxhighlight lang=pascal>
   Width <div class="symbol">=</div> <div class="int">400</div>
+
object VerticalSplitter: TPairSplitter
   <div class="key">object</div> Pairsplitterside1: TPairSplitterIde
+
   Align = alClient
     <div class="key">object</div> HorizontalSplitter: TPairSplitter
+
   SplitterType = pstVertical
       Align <div class="symbol">=</div> alClient
+
   Position = 225
       Position <div class="symbol">=</div> <div class="int">125</div>
+
   Height = 300
       <div class="key">object</div> Pairsplitterside3: TPairSplitterIde
+
   Width = 400
         Width <div class="symbol">=</div> <div class="int">125</div>
+
   object Pairsplitterside1: TPairSplitterIde
         <div class="key">object</div> LeftPanel: TPanel
+
     object HorizontalSplitter: TPairSplitter
           Align <div class="symbol">=</div> alClient
+
       Align = alClient
           Width <div class="symbol">=</div> <div class="int">125</div>
+
       Position = 125
         <div class="key">end</div>
+
       object Pairsplitterside3: TPairSplitterIde
       <div class="key">end</div>
+
         Width = 125
       <div class="key">object</div> Pairsplitterside4: TPairSplitterIde
+
         object LeftPanel: TPanel
         <div class="key">object</div> MainPanel: TPanel
+
           Align = alClient
           Align <div class="symbol">=</div> alClient
+
           Width = 125
         <div class="key">end</div>
+
         end
       <div class="key">end</div>
+
       end
     <div class="key">end</div>
+
       object Pairsplitterside4: TPairSplitterIde
   <div class="key">end</div>
+
         object MainPanel: TPanel
   <div class="key">object</div> Pairsplitterside2: TPairSplitterIde
+
           Align = alClient
     <div class="key">object</div> BottomPanel: TPanel
+
         end
       Align <div class="symbol">=</div> alClient
+
       end
       Height <div class="symbol">=</div> <div class="int">75</div>
+
     end
     <div class="key">end</div>
+
   end
   <div class="key">end</div>
+
   object Pairsplitterside2: TPairSplitterIde
<div class="key">end</div>
+
     object BottomPanel: TPanel
 +
       Align = alClient
 +
       Height = 75
 +
     end
 +
   end
 +
end
 +
</syntaxhighlight>
 
|}
 
|}
  
===TCustomTreeView/TTreeView===
+
===TCustomTreeView、およびTTreeViewについて===
Both VCL and the LCL provide a TCustomTreeView/TTreeView component, used for tree structured lists of data with multiple nodes and advanced selection and Image lists, and while actual features are comparable, not all properties are entirely compatible. Primary differences are as follows -
+
 
 +
VCLにもLCLにも、TCustomTreeView/TTreeViewのコンポーネントがあります。
 +
ツリー構造化されたデータのリストで、複数のノードや、高度なセレクション、イメージリストなどの機能があります。
 +
多くの機能は同等ですが、すべてのプロパティがまったくおなじではありません。主な相違点は以下です。
  
 
'''Incomplete list, also update to include TCustomTreeView Mark functions and protected methods '''
 
'''Incomplete list, also update to include TCustomTreeView Mark functions and protected methods '''
  
The LCL provides a TCustomTreeView.Options, a set of options which can be set on the control to change its behaviour and apearance. These options are :
+
LCLには、 TCustomTreeView.Optionsがあります。これは、コントロールが変更されたときのふるまいと見かけのオプションです。これらのオプションは次の通りです。:
#* tvoAllowMultiselect - enables multi node select mode, equivalent to enabling TCustomTreeView.MultiSelect in the D6 VCL
+
#* tvoAllowMultiselect - 複数のノードを選択できるモードです。eDelphi6のVCLのTCustomTreeView.MultiSelectと同等です。
#* tvoAutoExpand - Auto Expand nodes, equivalent to enabling TCustomTreeView.AutoExpand
+
#* tvoAutoExpand - ノードを自動展開します。TCustomTreeView.AutoExpandと同様です。
#* tvoAutoInsertMark - Update the Drag preview on mouse move.
+
#* tvoAutoInsertMark - マウスが上を動くとドラッグのプレビューを更新します。
#* tvoAutoItemHeight - Adjust the item heights automatically.
+
#* tvoAutoItemHeight - Itemの高さを自動的に調節します。
#* tvoHideSelection - Do not mark the selected item.
+
#* tvoHideSelection - 選択したItemをマークしません。
#* tvoHotTrack  - use Hot Tracking, equivalent to enabling TCustomTreeview.HotTrack
+
#* tvoHotTrack  - ホットトラッキングをおこないます。TCustomTreeview.HotTrackを有効にするのと同等です。
#* tvoKeepCollapsedNodes - When shrinking/folding nodes, keep the child nodes
+
#* tvoKeepCollapsedNodes - ノードを折畳んだりしたときに、子ノードを維持します。
#* tvoReadOnly - make Treeview read only, equivalent to enabling TCustomTreeview.ReadOnly
+
#* tvoReadOnly - TreeviewをReadOnlyにします。TCustomTreeviewのReadOnlyを有効にするのと同等です。
#* tvoRightClickSelect - allow using Mouse Right Clicks to select nodes, equivalent to enabling TCustomTreeView.RightClickSelect
+
#* tvoRightClickSelect - ノードをマウスの右クリックで選択状態にできるようにします。TCustomTreeView.RightClickSelectを有効にするのと同等です。
#* tvoRowSelect  - allow selecting rows, equivalent to enabling TCustomTreeView.RowSelect
+
#* tvoRowSelect  - 行選択を可能にします。TCustomTreeView.RowSelectを有効にするのと同等です。
#* tvoShowButtons  - show buttons, equivalent to enabling TCustomTreeView.ShowButtons
+
#* tvoShowButtons  - ボタンを表示します。TCustomTreeView.ShowButtonsを有効にするのと同等です。
#* tvoShowLines - show node lines, equivalent to enabling TCustomTreeView.ShowLines
+
#* tvoShowLines - ノードへの線を表示します。TCustomTreeView.ShowLinesを有効にするのと同等です。
#* tvoShowRoot  - show root note, equivalent to enabling TCustomTreeView.ShowRoot
+
#* tvoShowRoot  - ルートノードを表示します。TCustomTreeView.ShowRootを有効にするのと同等です。
#* tvoShowSeparators  - show seperators
+
#* tvoShowSeparators  - セパレータを表示します。
#* tvoToolTips - show tooltips for individual nodes
+
#* tvoToolTips - 個々のノードに、ツールチップを表示します。
# The LCL provides additional properties:
+
# LCLは次のプロパティを追加しました:
#* TCustomTreeView.OnSelectionChange event
+
#* TCustomTreeView.OnSelectionChange イベント
#* TCustomTreeView.DefaultItems, for the default number of Items
+
#* TCustomTreeView.DefaultItems, アイテムのデフォルト設定のためのものです。
#* TCustomTreeView.ExpandSignType to determine sign used on expandable/collapsible nodes
+
#* TCustomTreeView.ExpandSignType ノードの展開、折りたたみの際のサインを決定します。
# While most On Drag/Dock Events are available in the LCL they do not work. For more information please see earlier section on Control Dragging/Docking.
+
# LCLにあるほとんどのドラッグ、ドッキングイベントは動作しません。これについてのより詳細な情報は、前の「ドラッグとドッキングの制御」を見てください。
 +
 
 +
=== Messages / Events ===
 +
 
 +
The order and frequency of messages and events (OnShow, OnActivate, OnEnter, ...) differ from the VCL and depend on the widgetset.
 +
The LCL provides a subset of WinAPI like messages to make porting of Delphi components easier, but almost all LCL messages work a little bit different than the VCL/WinAPI counterpart. The biggest part of Delphi code using WinAPI messages uses them, because the VCL lacks a feature or for speed reasons. Such things will seldom work the same under the LCL, so they must be checked manually. That's why LCL messages are called for example LM_SIZE instead of WM_SIZE (unit lmessages).
 +
 
 +
'''Note on handling of custom messages!'''
 +
As of version 0.9.26 (December 2008), way of handling custom WinApi messages (e.g. WM_HOTKEY, WM_SYSCOMMAND) differs from the way of handling these messages in Delphi. At the moment you cannot handle them via '''message''' directive or via overriding of ''WndProc'' method of the form. The only way to handle them in the form is to hook Windows ''windowproc'' by yourself. Read more here: [[Win32/64_Interface#Processing_non-user_messages_in_your_window | Processing non-user messages in your window]]
  
 
==Original Contributors and changes==
 
==Original Contributors and changes==
Line 518: Line 512:
 
* Fixed some typos - [[User:Vincent | Vincent]] 10/2/2003
 
* Fixed some typos - [[User:Vincent | Vincent]] 10/2/2003
 
* Fixed Typo [[User:Kirkpatc]] 20 May 2004
 
* Fixed Typo [[User:Kirkpatc]] 20 May 2004
 +
 +
==See Also==
 +
[[Code Conversion Guide| Code Conversion Guide (from Delphi & Kylix)]]
 +
 +
[[Compile With Delphi]]

Latest revision as of 00:54, 19 February 2020

Deutsch (de) English (en) español (es) français (fr) 日本語 (ja) 한국어 (ko) português (pt) русский (ru) slovenčina (sk)

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

この記事は、Lazarusに興味があり、すでにDelphiは知っている、という人々向けのものです。 この二つの違いについて記述しています。

DelphiからLazarusへ

Lazarusは Delphiと同じく、RAD(Rapid Application Development、手早くアプリケーションを開発できる)ツールの一つです。ビジュアルなコンポーネントライブラリと、IDEがあります。Lazarusのコンポーネントライブラリ(LCL)はDelphiのVCLととても似ています。ほとんどのユニットと、クラスと、プロパティは、同じ名前と機能をもっています。これは、移植を簡単にします。しかし、Lazarusは'オープンソースのDelphiクローン'ではありません。ですから、100%の互換性を期待しないでください。

最大の相違点は?

Lazarusは完全にオープンソースで、プラットホームに対し独立しており、強力なFree Pascalコンパイラ(FPC)を使っています。FPCは15以上のプラットホームで動作します。しかし、すべてのパッケージやライブラリが移植されているわけではありません。ですから、Lazarusは現在のところLinux,FreeBSD,MaxOSX、そしてWin32上で動作します。(訳注:いくつかのPDAでも暫定的な動作はします。日本語に関する処理の改善に、これから皆さんの力を必要としています。)

Lazarusは、この文章がまたそうであるように、常に未完です。私たちはいつでも、新しい開発者、パッケージ管理者、移植者、ドキュメントの執筆者を募っています。

Delphi のプロジェクトを Lazarus 用に変換するためにまず必要なこと

Lazarus を起動し、 Tools メニューから Convert Delphi Project to Lazarus Project を選んで下さい。これで全てが解決する訳ではありませんが、大変役立つはずです。Lazarus IDE の変換ツールは一般に一方通行であり、逆の変換はできないことに注意して下さい。プロジェクトを Delphi でも Lazarus でもコンパイルできるように Delphi との互換性を維持する必要がある場合は、Lazarus IDEではなく XDev Toolkit の利用を考えて下さい。

ユニコードのサポート

2007バージョンまでの Delphi はユニコードをサポートせず、Windows が利用していた ANSI エンコーディングを採用していました。2008バージョン以降の Delphi はユニコードをサポートするようになり、UTF-16 を用いて文字列をエンコードしています。

一方、Lazarus は UTF-8 を用いたユニコードサポートを始めました。詳しくは LCL Unicode Support を御読みください。.

Delphi IDE から Lazarus IDE へ

プロジェクト

Delphiアプリケーションのメインのファイルは .dprファイルです。Lazarusにおいては、.lpiファイルです(=Lazarus Project Information)。 .dprファイルはメインのソースプログラムであり、DelphiのIDEはコンパイラスイッチやユニットなどの情報の一部を入れます(訳注:すべてではない。オプションファイルなどがある)。Lazarusのアプリケーションもメインのソースファイルを.lprファイルに入れます。しかし、そのほかのすべての情報をも入れます。ですから、.lpiファイルはとても重要です。

例: Delphiはユニットへのパスを.dprファイルに入れます。たとえば、unit1 in 'path/Unit1.pas'というふうにいれます。このinでパスを指定する方法はDelphi独特であり(Pascalの文法ではないので)、Lazarus IDEは読むことができないので、こういう方法をつかわないでください。かわりに、コンパイラオプションで、ユニットパスを指定してください。

Delphiはコンパイラオプションを.dprファイルに埋め込みます。たとえば、{$APPTYPE CONSOLE}.というふうにいれます。Lazarus IDEでは、これらは無視されますので、使わないで下さい。かわりに、コンパイラオプションを使ってください。

(訳注:DelphiのdprファイルはPascalの仕様+独自の部分が結構多いですが、Free Pascal Compiler上のLazarusとしては、Free Pascalに特殊な言語拡張をなるべく行わず、純粋にFree Pascal上に実現できるような方法がとられています。Delphiのようにコンパイラオプションを至る所に定義できるのは、便利でもある一方、スキャンしていかないと、有効か無効かが分からず、バグや全体のみとおしが悪くなる両刃の剣といえますので、訳者は良い仕様だと思います。)


ひとつ重要なルールがあります。それは、常にプロジェクトは存在するということです(訳注:IDEが起動している最中に、ということでしょう)。 現在のプロジェクトを"close"する方法は、lazarusを終了するか、他のプロジェクトを開くしかありません。 これは、lazarusのプロジェクトはセッションとしての役割があるからです。これは、現在のエディタの設定が、.lpiファイルに記録され、そのプロジェクトを開いたときに再開できるようになっています。たとえば、あなたがアプリケーションをデバッグしていて、多くのブレークポイントやブックマークを開いていたとしましょう。あなたは、いつでもプロジェクトを保存することができ、lazarusを終了したり、他のプロジェクトを開くことができます。その、デバッグ中に保存したプロジェクトを開くと(たとえ他のコンピュータで開いたとしても)、ブレークポイント、ブックマーク、開いていたファイル、カーソル位置、ジャンプヒストリ、などといったものが、復元できます。

ソースエディタ

ほとんどすべてのキーとショートカットが、enviroment -> editor options->key mappingsで定義可能です。 LazarusのIDEには、ソースのための沢山のツールがあります。それらの多くは、Delphiと見た目も似ており、よくにた働きをします。しかし、一つの重要な相違点があります。すなわち、Lazarusはコード情報を取るために、コンパイラを利用しない、ということです。ソースコードを直接解析します。こうすることで、沢山の重要な利点があります。

ソースエディタは、"comments"と一緒に動作します。Delphiにおいては、ソース中のコメントは、コードの間の場所にあるものにすぎません。自動でコードが挿入されても、特別な働きはしないので、すでに入れたコメントは迷子になってしまうかもしれません。Lazarusでは、コメントの中のコードでさえ、宣言を見つけることができます。 これは、完璧に信頼できるものではないかもしれませんが、よく役に立ってます。新しいコードが挿入されると、IDEは発見的な方法を使ってコメントとコードを結び付けます。たとえば、"c: char; // comment"という行は分割されることはありません。

Delphiの"コード補完"(Ctrl+Space)機能は、Lazarusでは、"Identifier Completion"と呼ばれます。Lazarusにおいて、コード補完は、"自動的なクラス補完"(Delphiとおなじです)、"ローカル変数補完"、"イベント割り当て補完"のあわせた機能です。これらのすべては、Ctrl+Shift+Cで呼び出され、IDEは、カーソルの位置から、何をなすべきか決定します。

ローカル変数補完の例

ちょうど新しいメソッドを作り、"i:=3;"という命令を書いたとしましょう。

procedure TForm1.DoSomething;
begin
  i := 3;
end;

識別子"i"の上にカーソルをおいて、Ctrl+Shift+Cを押すと、次のようになります。

procedure TForm1.DoSomething;
var
  i: Integer;
begin
  i := 3;
end;

イベント割当補完の例

オブジェクトインスペクタの良い機能のひとつに、自動的にメソッドを作ること、があります。ソースエディタでやってみてください。

たとえば:

Button1.OnClick:=

代入演算子":="の後で、Ctrl+Shift+Cを押してみてください。

手続呼出補完の例

今 "DoSomething(Width);" という文を書き終えた所だとします:

procedure SomeProcedure;
var
  Width: integer;
begin
  Width:=3;
  DoSomething(Width);
end;

識別子 "DoSomething" の上にカーソルを置いて、Ctrl+Shift+C を押すと、こうなります:

procedure DoSomething(aWidth: LongInt);
begin

end;

procedure SomeProcedure;
var
  Width: integer;
begin
  Width:=3;
  DoSomething(Width);
end;

語彙補完 Ctrl+W

識別子補完と似ていますが、パスカルの識別子に対してではなく、すべての語彙に対して補完します。あなたが開いているすべてのファイルの中から、あなたがタイプし始めた文字が同じものの語彙をリストアップし、選択できます。

インクルードファイルのサポート

Delphiではインクルードファイルをサポートしていませんので(訳注:$iがあるので、補完機能が、ということだろう)、多分、みなさんは多くのインクルードファイルを今までに作っていないかもしれません。しかし、インクルードファイルには、大きな利点があります。それは、IFDEFでソースコードを汚さずに、プラットホーム独立なコードを書けるということです。 Lazarusでは、メソッドジャンプ、クラス補完、宣言を見つける、など、すべての機能は、インクルードファイルに対しても働きます。 また、コーディング機能にいろんなオプションがあります。

デザイナ

- ガイドライン

オブジェクト・インスペクタ

DelphiとLazarusのIDEでは、オブジェクトインスペクタはコンポーネントプロパティを編集したり、イベントを設定したりするのに使われます。使い方に、いくつかの小さな違いがあります。

  1. Delphi5を起動すると、オブジェクトインスペクタのなかで、階層にしたがって伝統的なドロップダウンリストでオブジェクトを選択できるオブジェクトツリービューがあります。Lazarusでは、これは、オブジェクトインスペクタの一部にすぎません。デフォルトのドロップダウンリストのかわりに、右クリックで表示される"Show Component Tree"メニューを使うこともできます。
  2. Delphiでは、空のイベントでダブルクリックすると、自動的にイベントを作成し、ソースエディターがその位置を開きます。Lazarusは右側にボタンがあり、ドロップダウンでイベントを作成することができます。
  3. Delphiでは、つけられたイベント名は手で消さなくてはなりませんが、Lazarusでは、"(None)"をドロップダウンで選ぶことができます。
  4. Eventと同じように、booleanのような標準的なプロパティをダブルクリックすることでは、値は変化しません。値を変えるには、ドロップダウンで選択する必要があります。そして、エディターフォームで結び付けられているものを開くには、editやdrop-downの右側にある'...'ボタンをクリックする必要があります。

パッケージ

LazarusはDelphiのパッケージをインストールして使うことはできますか?

いいえ、なぜなら、それには、Delphiのコンパイラマジック(訳注:Pascalではない部分の特殊な文法)が必要だからです。

私たちは、Lazarus向けに特別にパッケージを作りたいのですが?

はい。新しくパッケージをつくり、パッケージソースディレクトリに保存してください。 通常は dpkファイルと同じディレクトリです。そして、LCLを必要とするパッケージとして加えて、最後に.pasファイルを加えてください。それを今すぐインストールしたり、プロジェクトで使うことができます。 LazarusとDelphiのパッケージで、いくつかの違いがありますので、lazarusのソース内のdocs/Packages.txtを読んでください。



VCL から LCL へ

VCLとLCLは、ともに、高速なアプリケーション開発向けの、オブジェクト指向の階層的なコンポーネントのライブラリです。しかし、それらは同じではありません。 たとえば、VCLは多くの非ビジュアルなコンポーネントを含みます。一方、LCLは、Free Pascalによって、多くの「ビジュアルでない」コンポーネント(データベースアクセスなど)が提供されていますので、ビジュアルなコンポーネントのみ、を提供しようとしています。 (訳注:データベースの表示については、ビジュアルである。そのなかで使われるデータベースアクセス自体はLCLコンポーネント内に統合されていると思われる)


加えていうと、VCL等にある多くのコントロールが、LCLには存在しないかもしれませんし、同じようなコントロールが両方に存在する場合でも、それらはクローンではありません。 ですから、もし移植をするなら、アプリケーション、コンポーネント、およびコントロールのそれぞれで変更が必要です。

次のことはDelphiユーザのために、DelphiとLazarusの主要な違いや、互換性のない所を、包み隠さずに明らかにしようとするものです。これは、主にD4でのVCL(D5,D6,D7も同様です)と、現在のCVSに、あるがままのLCLの違いをカバーしました。あなたがいつも使っているDelphiやLCLのバージョンに完全に一致しないかもしれません。もし、これらの記述が正確でないとすれば、他の皆さんの理解のために、ご自由に記述を加えたり、変更してください。

TControl.Font/TControl.ParentFontについて

VCLでは、コントロールにフォントのプロパティとして、ボールドやイタリック、特定のフォント名と等を使用し、通常はこの値がいつも子へと引き継がれていきます。 さらに、コントロールがいつもParentのフォントを確実にする継承するために、TControl.ParentFontプロパティを提供しています。 OSにウインドウの見え方の設定があるのですが、コントロールのプロパティが常時優先されるということを暗に決めてつけてしまっています。

(訳注:Windowsで画面で大きい文字などが選択できるが、他のデスクトップではもっと多くのことが指定できるものがあるので、Delphiにおいてもシステムフォントを取得することが望ましい、とされる場合もあるが、きっちりデザインが難しくなる。)

このフォントについての機能、解釈はLCLでは、異なっています。 現実にクロスプラットフォーム/クロスインタフェースであるLCLは、バランスのとれた手法を好んで採用しようとしています。LCLは、いつでも、どんなウィジェットでのネイティブのDesktop/ツールキットのApearance、Theme設定も使用しようとします。 例えば、テーマが、ボタンのための特定の字体を供給するGTKインタフェース、およびgtkを使用することがありますが、LCLボタンはいつもこのテーマに沿った字体を使用します。

このことは、ほとんどのLCLコントロールはVCLで当たり前になっている、設計上のフォントなどの管理機能は持っていない、ということです。 しかし、もし、この仕様を変更したければ、使用されるインターフェースにかかわらず、この様に統一的に割り当てられたインタフェースに代わり、Canvasに独自で描画するカスタムコントロールを使うことができます。

例えば太字や、特別な色の字体のLabelが必要な場合、代わりにTStaticTextを使用しなければなりません。 なぜなら、TLabelは特定のコントロールのインタフェースであり、すべてのインタフェースのネイティブなバージョンを供給するのであるならば、その大部分は、すべての環境が考慮されないかもしれない、デフォルトの設定が利用されるでしょう。

ドラッグとドッキングの制御

VCLでは、実行中に、例えば1個のパネルからコントロールをドラッグして、別のパネルにドッキングできるように、ほとんどのTWinControlからの派生コントロールは、ドラッグ、ドッキングを制御する機能が組み込まれています。

この機能はLCLでは、現在、未完成であり、実装されていません。現在、設計の初期段階です。このタイプのふるまいが、同じような方法で、同等のレベルの互換性を維持するように、最終的には、サポートしてくれると思います。

これは、現在、どんなControlも以下のTControlの機能、プロシージャ、プロパティを継承していない、使っていない、ということを意味します。

Protected
  function GetDockEdge(MousePos: TPoint): TAlign;
  function GetDragImages: TDragImageList;
  function GetFloating: Boolean;
  function GetFloatingDockSiteClass: TWinControlClass;
  procedure DoEndDrag(Target:TObject); X, Y: Integer);
  procedure DockTrackNoTarget(Source: TDragDockObject; X, Y: Integer);
  procedure DoEndDock(Target: TObject; X, Y: Integer);
  procedure DoDock(NewDockSite: TWinControl; var ARect: TRect);
  procedure DoStartDock(var DragObject: TDragObject);
  procedure DragCanceled;
  procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
                    var Accept: Boolean);
  procedure DoEndDrag(Target: TObject; X, Y: Integer);
  procedure DoStartDrag(var DragObject: TDragObject);
  procedure DrawDragDockImage(DragDockObject: TDragDockObject);
  procedure EraseDragDockImage(DragDockObject: TDragDockObject);
  procedure PositionDockRect(DragDockObject: TDragDockObject);
  procedure SetDragMode(Value: TDragMode);
  property DragKind: TDragKind;
  property DragCursor: TCursor;
  property DragMode: TDragMode;
  property OnDragDrop: TDragDropEvent;
  property OnDragOver: TDragOverEvent;
  property OnEndDock: TEndDragEvent;
  property OnEndDrag: TEndDragEvent;
  property OnStartDock: TStartDockEvent;
  property OnStartDrag: TStartDragEvent;
public
  function Dragging: Boolean;
  function ManualDock(NewDockSite: TWinControl; DropControl: TControl;
                     ControlSide: TAlign): Boolean;
  function ManualFloat(ScreenPos: TRect): Boolean;
  function ReplaceDockedControl(Control: TControl; NewDockSite: TWinControl;
                      DropControl: TControl; ControlSide: TAlign): Boolean;
  procedure BeginDrag(Immediate: Boolean; Threshold: Integer);
  procedure Dock(NewDockSite: TWinControl; ARect: TRect);
  procedure DragDrop(Source: TObject; X, Y: Integer);
  procedure EndDrag(Drop: Boolean);
  property DockOrientation: TDockOrientation;
  property Floating: Boolean;
  property FloatingDockSiteClass: TWinControlClass;
  property HostDockSite: TWinControl;
  property LRDockWidth: Integer;
  property TBDockHeight: Integer;
  property UndockHeight: Integer;
  property UndockWidth: Integer;

that the following classes do not exist/are unusable -

TDragImageList = class(TCustomImageList)
TDockZone = class
TDockTree = class(TInterfacedObject, IDockManager)
TDragObject = class(TObject)
TBaseDragControlObject = class(TDragObject)
TDragControlObject = class(TBaseDragControlObject)
TDragDockObject = class(TBaseDragControlObject)

下記の関数も、利用できないか、互換性がありません。

function FindDragTarget(const Pos: TPoint;
                         AllowDisabled: Boolean) : TControl;
procedure CancelDrag;
function IsDragObject(sender: TObject): Boolean;

TEdit、および、TCustomEditについて

Editコントロールは、LCLもVCLと同等の機能をもっていますが、移植中に、いくつかの気をつけるべき点があります。

  1. GUIインターフェースでの制限で、TEdit.PasswordCharはすべてのインタフェースでは、まだ正常に機能しません。入力テキストを隠するために必要とする場合は、代わりに、TCustomEdit.EchoMode emPasswordを使用します。
  2. ドラッグ、ドッキングイベントはまだ実装されていません。詳しくは、 Control Dragging/Docking.
  3. フォントプロパティは、GUIの統一性のためにたいてい無視されます。詳しくは、 TControl.Font/TControl.ParentFont

(optional) TSplitter -> TPairSplitter

Please Improve Me

There is now a TSplitter control in the LCL, so no need to convert it.

Nevertheless, if you want, here it is explained:

The following is loosely based on questions by Vincent Snijders on the mailing list, and responses by Andrew Johnson:

In the VCL, "Splitting" controls, that is a handle which can be dragged between two components to give one more or less space then the other, is accomplished by a TSplitter. This is often seen, for instance in the Delphi IDE between the docked Code Explorer and Source Viewer.

The LCL provides its own Control called a TPairSplitter, which serves the same type of purpose, however it is not compatible, so "repairing" broken VCL code or Delphi DFM's will be necesary in the event of porting code, even though much is shared in common between the two.

So what exactly are the differences?

Well the biggest differences are a VCL TSplitter has no children, instead it is placed between two controls aligned properly, and allows resizing between them at runtime, regardless its own size. It must have two controls aligned on each size to do anything. A simple example would be form with a Left Aligned Panel, a left aligned Splitter, and a second client aligned panel. On run time you could then realign the size given each panel by dragging on the handle provided by this Splitter control.

On the LCL hand however, a TPairSplitter is a special kind of control, with two panels, and it can only be usefull if the controls to split are on these panels, but it will still perform a split between those panel whether or not anything is on them. So following the prior example, you would have a form with a TPairSplitter aligned client, and a panel aligned client on its left side, and a panel aligned client on its right side.

The other important difference is that in the VCl, since the TSplitter is its own TControl, then the position is kept relative to the other controls on resize, so for instance a client panel will grow while the other panels will not, thus the split position is relative to the alignment of the split controls,

In the LCL since the side panels are separate then the TPairSplitter has a Position property which is absolute relative to top or left. so on resize the actual position does not change according to contents, so a callback must be set to ensure the ratio is kept on resize if this is important.

For example if the Right side of a vertical split needs to have alClient like behaviour, you need to add a form resize callback which does something like :

PairSplitter.Position := PairSplitter.Width - PairSplitter.Position; 
So how can I convert existing code using TSplitter to the TPairSplitter?

If the splitter and controls are created within an actual function(like form oncreate), conversion shouldn't be too difficult, primarily reorganize the code to create the controls in order of new hierarchy and set the parents of the child controls to split to the left/top and right/bottom portions of the PairSplitter. An example of the changes being -

VCL LCL
var 
  BottomPanel: TPanel;
  VerticalSplitter: TSplitter;
  LeftPanel: TPanel;
  HorizontalSplitter: TSplitter;
  MainPanel: TPanel;

begin
  BottomPanel:= TPanel.Create(Self);
  with (BottomPanel) do
  begin
    Parent:= Self;
    Height:= 75;
    Align:= alBottom;
  end;

  VerticalSplitter:= TSplitter.Create(Self);
  with (VerticalSplitter) do
  begin
    Parent:= Self;
    Align:= alBottom;
  end;

  HorizontalSplitter:= TSplitter.Create(Self);
  with (HorizontalSplitter) do
  begin
    Parent:= Self;
    align:= alLeft;
  end;

  LeftPanel:= TPanel.Create(Self);
  with (LeftPanel) do
  begin
    Parent:= Self;
    Width:= 125;
    Align:= alLeft;
  end;

  MainPanel:= TPanel.Create(Self);
  with (MainPanel) do
  begin
    Parent:= Self;
    Align:= alClient;
    Caption:= 'Hello';
  end;
end;
var
  BottomPanel: TPanel;
  VerticalSplitter: TPairSplitter;
  LeftPanel: TPanel;
  HorizontalSplitter: TPairSplitter;
  MainPanel: TPanel;

begin
  VerticalSplitter:= TPairSplitter.Create(Self);
  with (VerticalSplitter) do
  begin
    Parent:= Self;
    Align:= alClient;
    Width:= Self.Width;
    Height:= Self.Height;
    SplitterType:= pstVertical;
    Position:= Height - 75;
    Sides[0].Width:= Width;
    Sides[0].Height:= Position;
  end;

  HorizontalSplitter:= TPairSplitter.Create(Self);
  with (HorizontalSplitter) do
  begin
    Parent:= VerticalSplitter.Sides[0];
    Width:= Self.Width;
    Height:= VerticalSplitter.Position;
    align:= alClient;
    SplitterType:= pstHorizontal;
    Position:= 125;
  end;

  LeftPanel:= TPanel.Create(Self);
  with (LeftPanel) do
  begin
    Parent:= HorizontalSplitter.Sides[0];
    Align:= alClient;
  end;

  MainPanel:= TPanel.Create(Self);
  with (MainPanel) do
  begin
    Parent:= HorizontalSplitter.Sides[1];
    Align:= alClient;
    Caption:= 'Hello';
  end;

  BottomPanel:= TPanel.Create(Self);
  with (BottomPanel) do
  begin
    Parent:= VerticalSplitter.Sides[1];
    Align:= alClient;
  end;
end;

So as you can see, farely consistant with most control hierarchy. And if you are familiar with DFM's, the changes needed for DFM->LFM conversion should be farely obvious from the above, as they are the same sort of changes in Parent/Owner etc.

So the above example would be something like -

Delphi DFM
(extraneous values removed)
Lazarus LFM
(most width, height, etc. removed)
object VerticalSplitter: TSplitter
  Height = 3
  Cursor = crVSplit
  Align = alBottom
end
object HorizontalSplitter: TSplitter
  Width = 3
  Align = alLeft
end
object BottomPanel: TPanel
  Height = 75
  Align = alBottom
end
object LeftPanel: TPanel
  Width = 125
  Align = alLeft
end
object MainPanel: TPanel
  Align = alClient
end
object VerticalSplitter: TPairSplitter
  Align = alClient
  SplitterType = pstVertical
  Position = 225
  Height = 300
  Width = 400
  object Pairsplitterside1: TPairSplitterIde
    object HorizontalSplitter: TPairSplitter
      Align = alClient
      Position = 125
      object Pairsplitterside3: TPairSplitterIde
        Width = 125
        object LeftPanel: TPanel
          Align = alClient
          Width = 125
        end
      end
      object Pairsplitterside4: TPairSplitterIde
        object MainPanel: TPanel
          Align = alClient
        end
      end
    end
  end
  object Pairsplitterside2: TPairSplitterIde
    object BottomPanel: TPanel
      Align = alClient
      Height = 75
    end
  end
end

TCustomTreeView、およびTTreeViewについて

VCLにもLCLにも、TCustomTreeView/TTreeViewのコンポーネントがあります。 ツリー構造化されたデータのリストで、複数のノードや、高度なセレクション、イメージリストなどの機能があります。 多くの機能は同等ですが、すべてのプロパティがまったくおなじではありません。主な相違点は以下です。

Incomplete list, also update to include TCustomTreeView Mark functions and protected methods

  1. LCLには、 TCustomTreeView.Optionsがあります。これは、コントロールが変更されたときのふるまいと見かけのオプションです。これらのオプションは次の通りです。:
    • tvoAllowMultiselect - 複数のノードを選択できるモードです。eDelphi6のVCLのTCustomTreeView.MultiSelectと同等です。
    • tvoAutoExpand - ノードを自動展開します。TCustomTreeView.AutoExpandと同様です。
    • tvoAutoInsertMark - マウスが上を動くとドラッグのプレビューを更新します。
    • tvoAutoItemHeight - Itemの高さを自動的に調節します。
    • tvoHideSelection - 選択したItemをマークしません。
    • tvoHotTrack - ホットトラッキングをおこないます。TCustomTreeview.HotTrackを有効にするのと同等です。
    • tvoKeepCollapsedNodes - ノードを折畳んだりしたときに、子ノードを維持します。
    • tvoReadOnly - TreeviewをReadOnlyにします。TCustomTreeviewのReadOnlyを有効にするのと同等です。
    • tvoRightClickSelect - ノードをマウスの右クリックで選択状態にできるようにします。TCustomTreeView.RightClickSelectを有効にするのと同等です。
    • tvoRowSelect - 行選択を可能にします。TCustomTreeView.RowSelectを有効にするのと同等です。
    • tvoShowButtons - ボタンを表示します。TCustomTreeView.ShowButtonsを有効にするのと同等です。
    • tvoShowLines - ノードへの線を表示します。TCustomTreeView.ShowLinesを有効にするのと同等です。
    • tvoShowRoot - ルートノードを表示します。TCustomTreeView.ShowRootを有効にするのと同等です。
    • tvoShowSeparators - セパレータを表示します。
    • tvoToolTips - 個々のノードに、ツールチップを表示します。
  2. LCLは次のプロパティを追加しました:
    • TCustomTreeView.OnSelectionChange イベント
    • TCustomTreeView.DefaultItems, アイテムのデフォルト設定のためのものです。
    • TCustomTreeView.ExpandSignType ノードの展開、折りたたみの際のサインを決定します。
  3. LCLにあるほとんどのドラッグ、ドッキングイベントは動作しません。これについてのより詳細な情報は、前の「ドラッグとドッキングの制御」を見てください。

Messages / Events

The order and frequency of messages and events (OnShow, OnActivate, OnEnter, ...) differ from the VCL and depend on the widgetset. The LCL provides a subset of WinAPI like messages to make porting of Delphi components easier, but almost all LCL messages work a little bit different than the VCL/WinAPI counterpart. The biggest part of Delphi code using WinAPI messages uses them, because the VCL lacks a feature or for speed reasons. Such things will seldom work the same under the LCL, so they must be checked manually. That's why LCL messages are called for example LM_SIZE instead of WM_SIZE (unit lmessages).

Note on handling of custom messages! As of version 0.9.26 (December 2008), way of handling custom WinApi messages (e.g. WM_HOTKEY, WM_SYSCOMMAND) differs from the way of handling these messages in Delphi. At the moment you cannot handle them via message directive or via overriding of WndProc method of the form. The only way to handle them in the form is to hook Windows windowproc by yourself. Read more here: Processing non-user messages in your window

Original Contributors and changes

This page has been converted from the epikwiki version.

  • Initial import and formatting - VlxAdmin 9/26/2003
  • Begin VCL -> LCL with a section on TSplitter -> TPairSplitter - Andrew Johnson 9/30/2003
  • Add TControl.Font/TControl.ParentFont to VCL -> LCL - Andrew Johnson 9/30/2003
  • Update TEdit/TCustomEdit section in VCL -> LCL - Andrew Johnson 10/1/2003
  • Add Control Dragging/Docking to VCL -> LCL - Andrew Johnson 10/1/2003
  • Added "Object Inspector" to Delphi IDE -> Lazarus IDE - Andrew Johnson 10/1/2003
  • Added initial "TCustomTreeView/TTreeView" to VCL -> LCL - Andrew Johnson 10/1/2003
  • Added introduction to VCL -> LCL - Andrew Johnson 10/1/2003
  • Fixed some typos - Vincent 10/2/2003
  • Fixed Typo User:Kirkpatc 20 May 2004

See Also

Code Conversion Guide (from Delphi & Kylix)

Compile With Delphi