Delphi Programming / Object Pascal
[掲載 2022年08月31日] [更新 2022年08月31日] Delphi 一般・その他 |
フォームを実装した DLL の作成 |
動作確認等 |
Windows 10 ビルド 19043 Pro 64 bit + Delphi XE5(UP2) Pro VCL-32 |
Delphi で,フォームを実装した DLL を作成する手順と,簡単なサンプルです. |
[備考]
32 ビットの DLL は,64 ビットの EXE では使用できません.64 ビットの DLL は 32 ビットの EXE では使用できません. |
[ファイル] [新規作成] で [その他] を選択します.起動したダイアログの左ペインの [Delphi プロジェクト] を選択して,右ペインの [ダイナミックリンクライブラリ],つまり,DLL を選択します. |
|
図1
[新規作成] [その他] のダイアログ
- 左ペインの
[Delphi プロジェクト] を選択
- 右ペインの
[ダイナミックリンクライブラリ] を選択
|
[ファイル] [プロジェクトに名前を付けて保存] で任意のフォルダに保存します.今回は SampleDLL という名前で保存しています.保存したら,[Ctrl] + [F9] でコンパイルします.DLL が作成されます.
下図は,出力先ディレクトリを . に変更してコンパイルした結果です.デフォルトの出力先は [Win21] フォルダの階層下です.これは,EXE ができる場所と同じです. |
|
図2
保存したファイル類
- [Ctrl] + [F9] でコンパイルしたので DLL がある
|
次にフォームを作成します.
[ファイル] [新規作成] で,[VCL フォーム] を選択します.この時現れるダイアログで,VCL フレームワークを有効するために [はい] をクリックします.
今回は TButton1 を 1 つだけ配置したフォームでテストしました.DLL を使用する側のフォームと区別するために,フォームの背景色を変更しています.フォームのアイコンも変更しました.
既存のフォームを使用する場合は,[プロジェクト] [プロジェクトに追加] で,既存のフォームのユニットを選択します. |
|
図3
フォーム設計時の画面
- TButton を 1 つ配置
- 背景色を変更
- フォームのアイコンも変更
|
オブジェクトインスペクタでフォームの名前を FormInDLL にします.
[ファイル] [名前を付けて保存] で,FormInDLLUnit.pas の名前で保存します.下図は,保存後のファイル一覧です. |
|
図4
保存ファイル類
- Smiley.ico は 16 x 16 のアイコンファイル
|
フォームのコードを次にようにして上書き保存します. |
unit FormInDLLUnit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TFormInDLL = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
FormInDLL: TFormInDLL;
implementation
{$R *.dfm}
procedure TFormInDLL.Button1Click(Sender: TObject);
begin
ModalResult := mrOK;
end;
end.
次に DLL のコードを作成します.今回は以下の以下のようにしました.uses 部のフォームのユニット名は,既に追加されているものと同じです.
この DLL は,フォームを ShowModal メソッドでモーダル表示する関数だけの実装となっています.
[Ctrl] + [F9] でコンパイルして,[Cstr] + [S] で上書き保存して IDE を閉じます. |
library SampleDLL;
uses
System.SysUtils,
System.Classes,
Winapi.Windows,
Vcl.Forms,
Vcl.Controls,
FormInDLLUnit in 'FormInDLLUnit.pas' {FormInDLL};
function FormShowModal(AppHandle: HWND): TModalResult; stdcall;
begin
Application.Handle:= AppHandle;
FormInDLL := TFormInDLL.Create(Application);
try
Result := FormInDLL.ShowModal;
finally
FreeAndNil(FormInDLL);
Application.Handle := 0;
end;
end;
exports
FormShowModal;
begin
end.
フォームを,Show メソッドでモードレス表示する場合は,DllProc の機能を使用して,初期化と終了処理が必要です.以下の記事を参考にしてください.
また,Application 変数 (TApplication) や Screen 変数 (TScreen) を利用す場合も,DllProc による初期化と終了の処理が必要です. |
DLL 内でフォームを生成する時,次のように Owner を nil にして生成した場合,DLL 内でフォームを表示すると,タスクバーにそのフォームがアイコンが追加されます. |
FormInDLL := TFormInDLL.Create(nil);
新規に VCL フォームアプリケーションを作成します.
フォームに TButton と TEdit を配置します.TEdit は,フォームのモーダル表示の動作確認用です.フォームのユニットのコードを,図の下のコードにします.
このプロジェクトを,DLL のプロジェクトのファイルと同じフォルダ内に保存します.[F9] で実行します.下図はその結果です.
今回は,DLL を EXE と同じフォルダ内に置いてテストしています. |
|
図5
EXE を実公して [Button1] をクリック
|
|
図6
DLL 内のフォームを [OK] をクリック
|
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function FormShowModal(AppHandle: HWND): TModalResult; stdcall; external 'SampleDLL.dll';
procedure TForm1.Button1Click(Sender: TObject);
begin
if FormShowModal(Application.Handle) = mrOK then begin
MessageBox(Handle, '[OK]', '結果', MB_ICONINFORMATION);
end;
end;
end.
前項のサンプルは,DLL が存在しないか,DLL が存在しても,その DLL 内に目的の関数や手続きが存在しない場合は,実行時に例外が発生します.
それを回避するには,次のように DLL を実行時にロードして使用します.これを DLLの動的ロード,あるいは動的リンクと言います.前項のように使用する場合を DLL の静的リンクと言うことがあります.
DLL を動的にロードして使用する場合は,DLL を任意のフォルダに置いて利用できます. |
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
// 使用する DLL 内の関数や手続きを型として定義して,その型の変数を宣言
// 型名と変数名は任意
type
TFormShowModal = function (AppHandle: HWND): TModalResult; stdcall;
var
FShowDlg : TFormShowModal;
//=============================================================================
// 型定義した DLL 内の関数を使用
//
// (1) DLL を LoadLibrary でロードして,そのハンドルを取得
// (2) DLL 内の目的の関数のアドレスを GetProcAddress で取得
// GetProcAddress の第 2 引数が,実際に使用する DLL 内の関数名または手続き名
// (3) DLL を使い終わったら FreeLibrary で解放処理
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LDllHandle : THandle;
begin
LDLLHandle := LoadLibrary('SampleDLL.dll');
if LDllHandle <> 0 then begin
try
@FShowDlg := GetProcAddress(LDllHandle, 'FormShowModal');
if @FShowDlg <> nil then begin
if FShowDlg(Application.Handle) = mrOK then begin
MessageBox(Handle, '[OK]', '結果', MB_ICONINFORMATION);
end;
end;
finally
FreeLibrary(LDllHandle);
end;
end;
end;
end.
|