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



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




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


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

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

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

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

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


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

この方法は下図のように [ユニット出力ディレクトリ] と [出力ディレクトリ] の値が空になって.EXE がプロジェクトファイルと同じフォルダ内に作成されるようになってしまいます.この状態ではターゲットプラットフォーム別,あいるは Debug, Release 別の EXE が作成できません.
必要であれば元の値を入力してください.この値は Delphi のバージョンによって異なることがあります.[新規] にプロジェクトを作成して確認した方が確実です.



DMFコンバータ 図2
上記の方法による結果
  • 出力ディレクトリが空になってしまう
DMFコンバータ 図3
元の出力ディレクトリの値
  • Delphi XE の場合

実行時に「未定義のエラー」が発生した場合は,該当箇所を削除するか,修正します.ただし全てが修正可能なわけではありません.より上の 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.


[備考 1]
プロジェクト関係のファイルを dpr, dfm, pas だけにする方法は,プロジェクトのオプションの設定が,ビルド構成の設定がない Delphi のプロジェクトを Delphi XE 等で開いた時と同じになります.必要に応じて修正が必要です.

[備考 2]
当サイトで提供ているプロジェクトには,dproj, res ファイルが含まれてします.
Delphi 2009 以降であれば,dproj, res ファイルを削除する必要はありません.dproj にはプロジェクト関係の設定があります.拡張子が local, identcache のファイルには,開発時の環境に依存する内容があるので必ず削除します.拡張子が ico, dcu のファイルも削除します.
dpr, dfm, pas ファイルだけにする方法は,Delphi 6 / 7 / 2007 のプロジェクトを Delphi 2009 以降で使用する場合と,その逆の場合に必要です.




01_デフォルトのプロパティの違いと Font 関係プロパティの確認


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


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

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


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

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


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




02_Color と ParentColor と ParentBackground プロパティの効果


TControl の派生コントロールには,そのコントロールの背景色を設定する Color プロパティを実装しているコントロール (コンポーネント) があります.
下図は,Windows 10 の Delphi 7(UP1) Pro で新規にプロジェクトを作成して,そのフォームに TToolBar,TCoolBar, TPanel,TButton を配置してコンパイルして実行した結果です.TButton 以外のコントロールには,オブジェクト・インスペクタの Color プロパティで色を設定しています.設定した色が反映されています.

TToolBar,TCoolBar 共に [Win32] タブにあり,デフォルトの Color プロパティ値は clBtnFace です.



DMFコンバータ 図9
Delphi 7 のプロジェクトでテスト
  • フォームに以下を配置
    TToolBar (1 番上)
    TCoolBar (その下)
    TPanel
    TButton
  • TButton 以外では Color プロパティで背景色を設定
  • Delpi XE 等でテーマを無効にした時もこれと同じ結果となる

下図はアプリケーションマニフェストを使用してコンパイルして実行した結果です.アプリケーションマニフェストは,以下の記事に掲載しているコードを使用しました.
アプリケーションマニフェストを使用すると,Windows のテーマに従った描画になります.その結果です.
ただし,Delphi 6(UP2) では,TPanel の Color プロパティが有効になり,この後の図と同じになります.

今回 Delphi 7 で作成したプロジェクトを,Delphi XE5,Delphi 10 などでコンパイルして実行した場合も同じ結果になります.Delphi XE5,Delphi 10 などの新しいバージョンの Delphi では,アプリケーションマニフェストが自動的に EXE に組み込まれるからです.



DMFコンバータ 図10
アプリケーションマニフェストを使用した場合
  • Delphi XE 等でテーマを有効にした時もこれと同じ結果となる

アプリケーションマニフェストを使用した状態で,フォームの OnCreate イベントで以下のコードを実行した結果です.TPanel だけは Color プロパティの値が有効になっています.Windows のコモンコントロール類 (ComCtrls ユニット内のコントロール類) は,システムのテーマに従った描画になります.その結果です.

TButton は Windows のボタンコントロールのラッパークラスです.テーマ使用の有無に関係なく,Color プロパティの設定は無効になります.TPanel は Delphi 特有のコントロールです.


procedure TForm1.FormCreate(Sender: TObject);
begin
  ToolBar1.ParentColor := False;
  CoolBar1.ParentColor := False;
  // Delphi 6 以前には TPanel.ParentBackground プロパティがないが,効果は以下と同じ
  Panel1.ParentBackground := False;
end;


DMFコンバータ 図11
TPanel だけは Color プロパティの設定が有効になる
  • Delphi XE 等でテーマを有効にした時もこれと同じ結果となる




03_コンパイルエラーとユニットファイルの文字化け


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


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


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

この時,ユニットファイルの文字は,おそらく,下図のように,文字化けしています.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コンバータ 図13
コードページの違いによる文字化け
  • ユニットファイルの先頭にも不明な文字がある (赤枠部分)




04_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}




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




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


コンパイル時にエラーが発生しなくても,作成した実行ファイル,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 の動作が異なることがあります.






07_WinProcs, WinTypes, DbiProcs, DbiErrs ユニット


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