掲示板システム
ホーム
アクセス解析
カテゴリ
ログアウト
Lazarus2.2.2 で DLL(フォーム付き)のフォームが表示されません。 (ID:150409)
名前
ホームページ(ブログ、Twitterなど)のURL (省略可)
本文
気になったのでやってみた。覚書きのコピペ。 サンプルコードで動作するかをテスト。 今回のサンプルコードは、コンソールアプリである。2022/08/30 URL --> https://wiki.freepascal.org/Form_in_DLL dll作成サンプル(DllDialog.dll)とテスト用メインサンプル(MainApp.exe)が書いてある。 なので、今回の場合、MainApp.exeのプロジェクトとDllDialog.dllのプロジェクトが必要になる。 Lazarusではプロジェクトインスペクターに複数のプロジェクトを共存できない 、制限が多分ある??。 プロジェクトを切り替えてコンパイルすることになる。 プロジェクトの切り替えは、「メニュー」-->「プロジェクト」-->「プロジェクトを開く」で選ぶ。 拡張子「lpi」のファイル。(最後の文字がアイ) 拡張子が「lpr」のファイル(最後の文字がアール)がメインプロジェクトのファイルになる。 サンプルの場合、 MainApp.exe用プロジェクトのファイル名は、「MainApp.lpr」にする。 DllDialog.dll用プロジェクトのファイル名は、「DllDialog.lpr」にする。 サンプルは小規模プログラムだったので1つのファイルだったが、 ソースコードを別ファイルで追加出来る。 追加するソースファイルの拡張子は「.pas」を使い、「Unit1.pas」の様にする。 プロジェクトの「要求されたパッケージ」欄に、「LCL」パッケージを追加する。 「LCL」は、標準的ボタンなどの基本パッケージである。 コンソールアプリなのにフォームを使うので必要。 追加しないと uses Interfaces,.... の処で コンパイルエラーになるからわかる。 「MainApp.lpr」 --------------- program MainApp; {$mode objfpc}{$H+} uses Interfaces, Classes, LCLType, Controls, StdCtrls, Forms, ExtCtrls; type TEnableDisableFormsCallBack = procedure(var FormList: Pointer); 「続く」 //{$R *.res} resファイルは無いので削除する begin Application.Initialize; Application.CreateForm(TMainForm, MainForm); DLLDialog_Init(@DisableFormsCallBack, @EnableFormsCallback); try Application.Run; finally DLLDialog_Final; end; end. 「ここまでが、MainApp.lpr」 =============== 「DllDialog.lpr」 --------------- // DLL with a form: これはコメントにする // library DllDialog; {$mode objfpc}{$H+} uses Interfaces, Classes, LCLType, StdCtrls, Controls, Forms, Dialogs; type TDLLDialog = class(TForm) 「続く」 procedure TDLLDialog.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); {$IFDEF LCLWin32} Params.WndParent := ParentFormHandle; {$ENDIF} end; begin Application.Initialize; end. 「ここまでが、DllDialog.lpr」 ================ コンパイルは「メニュー」-->「実行(R)」-->「コンパイル」で、出来る。 dllから先にコンパイルするのが吉。 ---------------- フォームを使ったプログラムをメインで作るなら、いつもの手順でプロジェクトを用意すればよい フォームをメインに使ったプログラムのサンプル。 フォームにはないも配置しなくてよい。 // フォームを使って「DllDialog.dll」を呼び出す // unit Unit1; {$mode objfpc}{$H+} interface uses Interfaces, Classes, LCLType, Controls, StdCtrls, Forms, ExtCtrls; type TEnableDisableFormsCallBack = procedure(var FormList: Pointer); TCreateButtonCallBack = procedure(Caption: PChar; OnClick: TProcedure); const {$IFDEF WINDOWS} DLLDialogLib = 'DLLDialog.dll'; {$ELSE} DLLDialogLib = 'DLLDialog.so'; {$ENDIF} // dllの静的リンクの宣言 procedure DLLDialog_Init(DisableFormsCallBack, EnableFormsCallback: TEnableDisableFormsCallBack); external DLLDialogLib; procedure DLLDialog_Final; external DLLDialogLib; procedure DLLDialog_ShowModal(ParentWindow: HWND); external DLLDialogLib; procedure DLLDialog_Show(ParentWindow: HWND); external DLLDialogLib; procedure DLLDialog_CreateDLLButton(ParentWindow: HWND); external DLLDialogLib; procedure DLLDialog_CreateButton(CreateButtonCallBack: TCreateButtonCallBack); external DLLDialogLib; type {TForm1} TForm1 = class(TForm) procedure FormCreate(Sender: TObject); private PnlParent: TPanel; // 変数をこっちに移動。 BtnShow, BtnShowModal, BtnAddDLLButton, BtnAddButton: TButton; procedure BtnAddDLLButtonClick(Sender: TObject); procedure BtnAddButtonClick(Sender: TObject); procedure ShowModalDLLDialog(Sender: TObject); procedure ShowDLLDialog(Sender: TObject); public end; // 実行時に関数のポインターを参照するので、このUnitに関数が有ることを宣言する procedure DisableFormsCallBack(var FormList: Pointer); procedure EnableFormsCallback(var FormList: Pointer); var Form1: TForm1; implementation {$R *.lfm} procedure DisableFormsCallBack(var FormList: Pointer); begin FormList := Screen.DisableForms(nil, TList(FormList)); end; procedure EnableFormsCallback(var FormList: Pointer); begin Screen.EnableForms(TList(FormList)); end; procedure CreateButtonCallBack(ACaption: PChar; AOnClick: TProcedure); var Btn: TButton; MyMethod: TMethod; begin //Btn := TButton.Create(MainForm); Btn := TButton.Create(Form1); // 変更 Btn.Caption := ACaption; Btn.Left := 100; Btn.Width := 100; Btn.Height := 20; MyMethod.Code := AOnClick; MyMethod.Data := nil; Btn.OnClick := TNotifyEvent(MyMethod); //Btn.Parent := MainForm.PnlParent; Btn.Parent := Form1.PnlParent; // 変更 end; { TForm1 } procedure TForm1.FormCreate(Sender: TObject); begin Position := poWorkAreaCenter; Width := 600; Height := 200; BtnShow := TButton.Create(Self); BtnShow.Parent := Self; BtnShow.Caption := 'Show form'; BtnShow.AutoSize := True; BtnShow.OnClick := @ShowDLLDialog; BtnShowModal := TButton.Create(Self); BtnShowModal.Parent := Self; BtnShowModal.Caption := 'Show modal form'; BtnShowModal.AutoSize := True; BtnShowModal.OnClick := @ShowModalDLLDialog; BtnShowModal.AnchorSide[akLeft].Control := BtnShow; BtnShowModal.AnchorSide[akLeft].Side := asrRight; BtnShowModal.BorderSpacing.Left := 10; BtnAddDLLButton := TButton.Create(Self); BtnAddDLLButton.Parent := Self; BtnAddDLLButton.Caption := 'Create real DLL button'; BtnAddDLLButton.AutoSize := True; BtnAddDLLButton.OnClick := @BtnAddDLLButtonClick; BtnAddDLLButton.AnchorSide[akLeft].Control := BtnShowModal; BtnAddDLLButton.AnchorSide[akLeft].Side := asrRight; BtnAddDLLButton.BorderSpacing.Left := 10; BtnAddButton := TButton.Create(Self); BtnAddButton.Parent := Self; BtnAddButton.Caption := 'Create fake DLL button'; BtnAddButton.AutoSize := True; BtnAddButton.OnClick := @BtnAddButtonClick; BtnAddButton.AnchorSide[akLeft].Control := BtnAddDLLButton; BtnAddButton.AnchorSide[akLeft].Side := asrRight; BtnAddButton.BorderSpacing.Left := 10; PnlParent := TPanel.Create(Self); PnlParent.Parent := Self; PnlParent.AnchorSide[akTop].Control := BtnShow; PnlParent.AnchorSide[akTop].Side := asrBottom; PnlParent.BorderSpacing.Top := 10; PnlParent.Width := 220; end; procedure TForm1.BtnAddButtonClick(Sender: TObject); begin DLLDialog_CreateButton(@CreateButtonCallBack); end; procedure TForm1.BtnAddDLLButtonClick(Sender: TObject); begin DLLDialog_CreateDLLButton(PnlParent.Handle); end; procedure TForm1.ShowDLLDialog(Sender: TObject); begin DLLDialog_Show(0); end; procedure TForm1.ShowModalDLLDialog(Sender: TObject); begin DLLDialog_ShowModal(Self.Handle); end; end. ---------------------- 「project1.lpr」に追加 Application.Initialize; Application.CreateForm(TForm1, Form1); // これを追加 DLLDialog_Init(@DisableFormsCallBack, @EnableFormsCallback); Application.Run; ---------------------- コンソールプログラムと同じ動作を確認した。 lazarusが入ってないPCで動作するかは未確認。 以上
←解決時は質問者本人がここをチェックしてください。
戻る
掲示板システム
Copyright 2021 Takeshi Okamoto All Rights Reserved.