喫茶XRAYトップページ

[スレッド全体
]

[312] Re4:DllでMainForm以外からのClose返信 削除
2005/6/20 (月) 07:50:31 Mr.XRAY
▼ りおりおさん

> ですから、一般には dll とそれを呼ぶ exe の間でクラスのインスタンスを渡して
> 操作することはできません。うまくいったとしても偶然と考えるべきです。


ははっ,そうですよね.

> Form を閉じるくらいなら、ウィンドウハンドルを渡すべきです。それなら、
> isWindow() で有効なウィンドウであるかどうか確認できますし、DestroyWindow や
> WM_SYSCOMMAND で SC_CLOSE を送れば閉じられます。


わかりました.初めてFormを表示するDLLを作成してみたのですが,作法を無視
してしまいました.とてもHalbow資料館のような内容を提供しているサイトの
管理者とは思えない(苦笑).

ありがとうごさいました.

[313] Re5:DllでMainForm以外からのClose返信 削除
2005/6/20 (月) 14:31:00 Syake
皆さんこんにちは
色々ありがとうございます。

if IsWindow({DLLFormのWindowハンドル}) then
begin
   SendMessage({DLLFormのWindowハンドル} ,WM_SYSCOMMAND,SC_CLOSE,0);
end;
これは、呼び出し側(EXE)から呼び出し先DllFormを閉じる処理ですね。

どうも、最初の説明が良くなくてすいません<m(__)m>
呼び出し側ではなく、呼び出し先の(DLLForm内)Unit2からDLLForm自体を
閉じようとしています。

DLLFormはForm1(Main)とForm2(Sub)で構成されています。
DLLForm呼出し後、DLLForm内の処理で、Form1(Main)でClose処理では
DLLFormは閉じる事ができますが、Form2(Sub)からでは閉じることが
できないでいます。

これが単体のEXEであれば、Application.Terminateを使うとか、Unit2から
Form1.Close(かまわないですよね?)を記述すれば終了できます。
・・・が、DLLFormでは当然前者は使えず、後者でやってしまえって事で、
記述したら「読み込み違反」となってしまいます。




[314] Re6:DllでMainForm以外からのClose Re5:追加返信 削除
2005/6/20 (月) 14:48:53 Syake
続きです
//=================EXE側
var
  Form1: TForm1;
implementation
   function OpenFrm(var WinHad :THandle):Boolean; stdcall; external 'OpenFrmTest.dll';
   procedure SyncApp(appHnd :THandle); stdcall; external 'OpenFrmTest.dll';
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
  SyncApp(Application.Handle);
  {DllFormが既にオープンされているか}
  if IsWindow(TestfrmWinHnd) = False then //(二重起動防止)
  begin
    if OpenFrmExCCTPrt(TestfrmWinHnd) = False then
    begin
       //;
    end;
 end;
end;

//=================DLLForm側
//----------------------frmMain
var
  frmMain: TfrmMain;
   function OpenFrm(var WinHad :THandle):Boolean;stdcall;
   procedure SyncApp(AppHnd :THandle); stdcall;
implementation
uses UfrmSub;
   function OpenFrm(var WinHad :THandle):Boolean;stdcall;
   begin
      frmMain := TfrmMain.Create(Application);
      frmSub := TfrmSub.Create(Application);
      try
         WinHad := frmMain.WindowHandle;
        frmMain.Show ;
        Result := True;
      except
         frmMain.Free;
        frmSub.Free;
        Result := False;
      end;
   end;
   procedure SyncApp(AppHnd :THandle);stdcall;
   begin
      //Application.Handle := AppHnd;//今回は使わない
   end;
procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   frmSub.Free;
   frmMain.Free;
end;

//----------------------FrmSub
procedure TfrmSub.Button1Click(Sender: TObject);
begin
   frmMain.Close;//DLLの読み込み違反
end;

一体、どうすればUnit2から閉じれるのか(^_^;)




[315] Re7:DllでMainForm以外からのClose Re5:追加返信 削除
2005/6/20 (月) 18:15:36 りおりお
こんにちは。

なにも問題なさそうですけど。

--------------- Exe ---------------------

function ShowTestForm(hOwner:HWND):HWND;stdcall;
                               external 'TestDll.dll' name 'ShowTestForm';

function ShowSubForm(hOwner:HWND):HWND;stdcall;
                               external 'TestDll.dll' name 'ShowSubForm';

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowTestForm(Application.Handle);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ShowSubForm(Application.Handle);
end;

---------------- DLL --------------------

--------------- project

library TestDll;

uses
  Forms,
  Windows,
  Controls,
  DllMain in 'DllMain.pas' {DllForm},
  DllUnit2 in 'DllUnit2.pas' {DllSubForm};

function ShowTestForm(hOwner:HWND):HWND;stdcall;
begin
  //Application.Handle := hOwner;
  DllForm := TDllForm.Create(Application);
  result := DllForm.Handle;
  DllForm.Show;
  //Application.Handle := 0;
end;

function ShowSubForm(hOwner:HWND):HWND;stdcall;
begin
  //Application.Handle := hOwner;
  DllSubForm := TDllSubForm.Create(Application);
  result := DllSubForm.Handle;
  DllSubForm.Show;
  //Application.Handle := 0;
end;

exports
  ShowTestForm,
  ShowSubForm;

begin
end.

[316] Re8:DllでMainForm以外からのClose Re5:追加返信 削除
2005/6/20 (月) 18:16:57 りおりお
つづき

--------------------

unit DllMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, DllUnit2;

type
  TDllForm = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  DllForm: TDllForm;

implementation

{$R *.dfm}

procedure TDllForm.Button1Click(Sender: TObject);
begin
  Close;
end;

procedure TDllForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
  if Assigned(DllSubForm) then DllSubForm.Release;
end;

end.

--------------------------

unit DllUnit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TDllSubForm = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  DllSubForm: TDllSubForm;

implementation

{$R *.dfm}

uses
  DllMain;

procedure TDllSubForm.Button1Click(Sender: TObject);
begin
  DllForm.Close;
end;

end.

--------------------

これで DllSubForm の Button1Click で両方閉じます。

[317] Re9:DllでMainForm以外からのClose Re5:追加返信 削除
2005/6/20 (月) 19:20:14 Syake
▼ りおりおさん
色々ありがとうございます。<m(__)m>

Helpで再確認したところ
「フォームまたはその子フォームのイベントハンドラでは
Free (Delphi) のかわりに Releaseを使う必要があります。
そうしないと,メモリアクセスエラーが発生することがあ
ります。」と親切に書いてありました。
procedure TfrmMain.FormClose(Sender: TObject;
        var Action: TCloseAction);
begin
   //frmMain.Free;
   Action := caFree;
   //frmSub.Free;{これは駄目でした}
  //if Assigned(frmSub) then frmSub.Release;{}
  frmSub.Release;
end;

この場合の Action := caFree と frmMain.Freeは同じ意味
で、動作に支障は無い。
frmMain以外のFormは「Release」としなければならない。
と、言うことでしょうか。

う〜む、では何でFrmMainからCloseしたら何もエラーが
出なかったのだろうか?
「メモリアクセスエラーが発生することがあります。」
だから、たまたまって事で、やはり「Release」て事かな。


[▼次のスレッド]
INCM/CMT
Cyclamen v3.82