Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2009年11月01日] [更新 2013年12月22日] Delphi 一般・その他
   
別バージョンで作成されたプロジェクトの利用
動作確認等 Delphi 5 〜 Delphi XE2
[整理番号 - 490]



  • 2011年10月16日
  • [Delphi Library 利用上の注意等] から記事をこちらに移動




別のバージョンで作成された Delphi プロジェクトの利用


異なるバージョンの Delphi で作成したプロジェクトを利用する時の参考です.

Delphi のプロジェクトやフォームを開く時,リソース関係の読み込みエラー等が発生することがあります.また,例えコンパイルができて,エラーが発生しなくても,作成した EXE が正常動作しない場合があります.これは,そのプロジェクトなりフォームが別のバージョンの Delphi で作成されている場合によく発生します.

Delphi のプロジェクトにはいろいろな拡張子のファイルがあります.各種の設定内容がこれらのファイルに記録されています.Delphi はバージョンや環境の違いを,これらのファイル内の内容でうまく管理していることになります.その内容に違いによってもエラー等が発生することがあります.
このような場合,一度プロジェクトを閉じ,下図のように,
  • リソースファイル (res)
  • コンパイル済みファイル (dcu)
  • 他のプロジェクト関係ファイル (dproj, dproj.local, identcache 等)
  • 設定情報ファイル等 (cfg や dof)
のファイルがあれば削除し,バージョンや環境に関係しないファイルだけを残します.そしてプロジェクトを再起動します.ソースコードに XPMan... が uses されていたらこれも削除します.この操作で関係するプロパティ類やリソースは失われます.必要に応じてリソースの設定を行います.

そして,そのプロジェクトに関係するコンパイル済みファイルや,バージョン依存関係ファイルを作成または更新するために,プロジェクトを [再構築] または [ビルド] します.
Delphi のバージョンよっては,アプリケーションアイコンの再設定が必要な場合があります.

本来は,削除しなければならないファイルだけを特定して,それだけを削除すればいいのですが,筆者は,この,最低限必要なファイルだけを残す方法で作業しています.

上記のプロジェクトファイル関係以外の,フォームやコードは.より新しいバージョンの Delphi で使用する場合はほとんど修正なしで使用可能です.



DMFコンバータ 図1
必要最小限のファイルのみにする
  • 拡張子が rc のファイルは削除しない
  • rc ファイル等で追加したリソースは失われるので,後でプロジェクトへの追加が必要
  • プロジェクトは [再構築] あるいは [ビルド] する

実行時に「未定義のエラー」が発生した場合は,該当箇所を削除するか,修正します.ただし全てが修正可能なわけではありません.より上の Delphi のバージョンで追加されているプロパティや関数などは修正が困難なこともあります.

例えば、下のリストのように、Delphi 2006 以前のバージョンでは、拡張子が .dpr のプロジェクトファイルの MainFormOnTaskbar プロパティは存在しません。
このため,Delphi 2006 以前の Delphi を Vista 以降の Windows で使用する際,[秘密のウインドウ] に対する対処が必要な場合があります.

開発環境と実行環境の OS のバージョンにも注意が必要です.新しい OS で追加された API を使用しているとか,その API が仕様変更していることもあります.


リスト1
バージョンによるプロジェクトのソースコードの違いの例
IDE から [プロジェクト] [ソースの表示] で表示した内容
program Project1;

uses
  Vcl.Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  //Delphi2007より前のバージョンではMainFormOnTaskbarプロパティはない
  //逆にDelphi2007以降ではこの行が必要(なければ追加する)
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.


プロパティのデフォルトの値が違っている場合もあります.
下図は AutoScroll プロパティの例です.Delphi XE のデフォルト値は False ですが,Delphi 6 のデフォルトの値は True です.そのため Delphi 6 では,フォームに配置したコントロールが,フォームのクライアント領域に収まらない時はフォームのスクロールバーが表示されます.


DMFコンバータ 図2
Delphi XE
  • AutoScroll プロパティのデフォルトの値は False
DMFコンバータ 図3
Delphi 6
  • AutoScroll プロパティのデフォルトの値は True

Font プロパティの設定にも注意が必要です.フォントサイズとフォント名によっては表示のデザインが違うことがあります.また,CharSet の値によっては,表示できない文字があります.


DMFコンバータ 図4
Font プロパティ
  • 左は Delphi 6 のデフォルト
  • 右は Delphi XE のデフォルト
  • 共に Windows 7 U64(SP1) 環境

下の最初の図は Windows 7 U64(SP1) の環境で,Delphi 6 のフォームに配置した TMemo の Font プロパティの設定画面です.文字セットが日本語になっています.その下の図は Delphi XE の設定画面ですが,文字セットが欧文になっています.
この状態で作成した Delphi XE のプロジェクトをそのまま Delphi 6 で使用すると,文字化けする可能性があります.


DMFコンバータ 図5
Delphi 6 の TMemo, TRichEdit のフォント設定ダイアログ
DMFコンバータ 図6
Delphi XE の TMemo, TRichEdit のフォント設定ダイアログ





コンパイルエラーとユニットファイルの文字化け -  Delphi 2007以前


新しいバージョンの Delphi のプロジェクトを,Delphi 2007 以前のバージョンで開きます.そして,コンパイルすると,以下のようなエラーが発生してコンパイルできないことがあります.


モジュール  でエラーが発生しました。TForm1 クラスの宣言が無いか間違っています.


DMFコンバータ 図7
コンパイルエラー

この時,ユニットファイルの文字は,おそらく,下図のように,文字化けしています.Delphi 2009 以降はユニコード化され,ユニットファイルも UTF-8 で保存されるために発生します.Delphi 2007 以前の Delphi の文字コードは Shift-JIS でなければ正常に表示されません.
このような場合は,以下の作業を行います.
  • (1) プロジェクトを保存しないで閉じる (保存してしまうと修復できない)
  • (2) テキストエディタ (メモ帳でもよい) でユニットファイルを開く
  • (3) [名前を付けて保存] で,文字コードを Shift-JIS または ANSI にして保存する
  • (4) 再度 Delphi の IDE でプロジェクトを開く
これで文字化けがなくなり,コンパイルが可能となります.ただし,Ansi 文字にはないユニコード文字は正確には表示されません.
Delphi 2007 以前の Delphi の String 型は AnsiString 型です.一方,Delphi 2009 以降の Delphi の String 型は ユニコード文字列として処理されます.


DMFコンバータ 図8
コードページの違いによる文字化け
  • ユニットファイルの先頭にも不明な文字がある (赤枠部分)




Delphi のバージョンによるコンパイル条件分岐


もし,Delphi のバージョンによる処理の分岐が必要であれば,以下の参考リンクの記事とコードを参考にしてください.

{$IFDEF CONDITIONALEXPRESSIONS} は,サポートしていなければ,これ以降のコードはコンパイルしないという指令です.{$IF Declared(CompilerVersion)} は,CompilerVersin が使えればコンパイルを実行するという意味です.CompilerVersin の代わりに RTLVersion も使用できます.

このコードで使用している CompilerVersion は Delphi 5 以前では使用できません.そこで,条件分岐を別にしています.その分だけ最後に {$ENDIF} が必要となります.
ユニコード関係の判定についてはリンクの記事を参考にしてください.




  {$IFDEF VER120}
    //Delphi 4 用のコード
  {$ELSE}
  {$IFDEF VER130}
    //Delphi 5 用のコード
  {$ELSE}
  {$IFDEF CONDITIONALEXPRESSIONS}
    {$IF Declared(CompilerVersion)}
      {$IF CompilerVersion >= 27.0}
        //Delphi XE6 以降用のコード
      {$ELSEIF CompilerVersion >= 23.0}
        //Delphi XE2 - Delphi XE5 用のコード
      {$ELSEIF CompilerVersion >= 20.0}
        //Delphi 2009 - Delphi XE 用のコード
      {$ELSE}
        //Delphi 6 - Delphi 2007 用のコード
      {$IFEND}
    {$IFEND}
  {$ENDIF}
  {$ENDIF}
  {$ENDIF}




Delphi 5 以前で使用


Delphi 5 よりも新しいバージョンの Delphi で作成されているフォームは,IDE では開けない場合があります.ほとんどの場合,DFM ファイルのコンバートが必要です.DEKO さんが提供している DFM コンバータを利用すると,Delphi 6 以上のフォームファイル (*.dfm) を Delphi 5 のテキスト形式の DFM ファイルにコンバートできます.

このコンバート操作が有効なのは 1 回だけです.コンバートした dfm ファイルに対して更にコンバートすると,コンバート後の文字コードが変換前の文字コードとして解釈されるため,正常な結果は得られませんので注意してください.
Delphi 5 よりも前のバージョンのフォームのコンバートについては,同じく DEKO さんのサイトの記事 [今更聞けない Delph iのコト (フォームファイル編)] も参考にしてください.

Delphi 5 のフォームを,Delphi 2009 以降の形式にするには,
  • [プロパティ文字列] を [DBCS 文字列 -> Unicode エンコード] に
  • [文字コードセット] を [ShiftJIS -> EUC] に
にします.逆に,Delphi 2009 以降のフォームを Delphi 5 でも使用可能なフォームにするには,
  • [プロパティ文字列] を [Unicode エンコード -> DBCS 文字列] に
  • [文字コードセット] を [EUC -> ShiftJIS] に
します.プロパティの文字列は指定しなくても変換できますが,指定した方がいいでしょう.



DMFコンバータ 図9
起動画面
  • Delphi 2009 以降のフォームを,Delphi 5 で使用可能にするには,右の [文字コードセット] を EUC->ShiftJIS にする




コンパイルできても正常動作するとは限らない


コンパイル時にエラーが発生しなくても,作成した実行ファイル,EXE が期待通り正常動作するとは限りません.
例えば,文字列の扱いには注意が必要です.Delphi 2007 以前の Ansi 版の Delphi では,文字列をバイト単位で扱います.一方,Unicode 版の Delphi 2009 以降では,文字単位での扱いとなります.
Windows Vista 以降の Windows では,自動的に Unicode 版の関数が使用されることがあります.したがって,Delphi 2007 以前の Delphi では,明示的に Ansi 版の関数を使うようにするとか,明示的に AnsiString 型にしないと期待通りの結果が得られないこともあります.

これらのことも含めて,EXE を作成した OS とは別のバージョンの OS では期待通りの動作にならない場合があります.実行時の環境によるテストが重要です.

開発するアプリのテストは,EXE 単独で起動してのテストも重要です.この時,Delphi の IDE が起動中と,IDE が起動していない場合とでは動作に違いが生じることもあります.
Delphi 6 / 7 のような旧バージョンはともかく,現在の Delphi の IDE は,DDE や .NET FrameWork の機能を利用しています.それらが有効な状態では EXE の動作が異なることがあります.





WinProcs, WinTypes, DbiProcs, DbiErrs ユニット


ここまで述べたことは,プロジェクトだけとは限りません.別のバージョンで作成されたコード,ユニットに対しても同じです.
16 ビット版の Delphi には WinProcs, WinTypes というユニットがありました.これらのユニットは現在は実装されていません.これらのユニットに含まれていた機能は,Windows.pas 内で提供されています. 同様なユニットに DbiTypes, DbiProcs, DbiErrs があります.