2012-03-09 5 views
5

使用できるイベントはありますか?ShowMessageが画面に表示される瞬間を捉えていますか?私はまた、メッセージを示した0​​への参照を渡す必要があります。ダイアログウィンドウフォーム(ShowMessage、MsgDialogなど)への参照を取得する

これまでのところ、私はOnDeactivateを試してみましたが、それはそう、ShowMessageがそれを引き起こしていない...

In.NETすべてのメッセージボックス(Application.AddFilterMessageまたはこのようななめらか)をキャッチし、アプリケーション上のmethonがあり、私は」ダイアログウィンドウが表示されている間 私は瞬間をキャッチする必要があります(または単にモーダルウィンドウを、それがその快適ではありません):デルファイ

にこのようなものが必要dは私がachiveしようとしていることです。私はその後、いくつかの指示をする必要があります。それらの指示の目的は、受け取ったばかりのDialogWindowに私に言いたいことを与えることです。例えば、その上にあるボタンの数を得ることができます。

+2

デビッドのコードがあなたが望むことをするかもしれませんが、私の最初の考えは、あなたが何かを回避する方法を探しているかもしれないということです。なぜあなたがこれを行う必要があるかによって、より良い方法があるかもしれません。これはデバッグのステップですか、誤った第三者のコントロール、テスト手順、または何かの回避策ですか? – MikeD

+3

多分あなたは[TApplication.OnModalBegin](http://docwiki.embarcadero.com/VCL/en/Forms.TApplication.OnModalBegin)や[TApplicationEvents.OnModalBegin](http://docwiki.embarcadero.com/VCL/)を使うことができます。 ja/AppEvnts.TApplicationEvents.OnModalBegin)? –

+0

@UlrichGerhardt私はこれが(明らかに)Delphi 2010以降のための最良の答えだと信じています。 –

答えて

6

最新のDelphiバージョンでは、現代のWindowsバージョンでは、ShowMessageがWindowsダイアログウィンドウになります。 WH_CBTフックを使用して、そのダイアログウィンドウのアクティブ化をキャッチすることができます。

function CBTProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; 
var 
    wnd: HWND; 
    ClassName: string; 
begin 
    if nCode=HCBT_ACTIVATE then 
    begin 
    wnd := wParam; 
    SetLength(ClassName, 256); 
    SetLength(ClassName, GetClassName(wnd, PChar(ClassName), Length(ClassName))); 
    if (ClassName='#32770') or (ClassName='TMessageForm') then 
     Beep; 
    end; 
    Result := CallNextHookEx(0, nCode, wParam, lParam); 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    Hook: HHOOK; 
begin 
    Hook := SetWindowsHookEx(WH_CBT, CBTProc, HInstance, GetCurrentThreadId); 
    if Hook=0 then 
    RaiseLastOSError; 
    try 
    ShowMessage('hello'); 
    finally 
    if not UnhookWindowsHookEx(Hook) then 
     RaiseLastOSError; 
    end; 
end; 

実際のウィンドウクラス名は、システムによって異なります。 XPでは、ダイアログは実際にはDelphi TFormなので、クラス名はTMessageFormになります。しかし、Vista以降では、ダイアログはウィンドウクラス名#32770を持つ標準的なウィンドウメッセージボックスダイアログです。

これは、ShowMessageへの1回の呼び出しでラッピングされていますが、アプリに表示されているすべてのメッセージダイアログボックスをフックする場合は、これを起動時にインストールできます。

+0

実際に私のアプリケーションに表示されるすべてのメッセージをホックしたいです。しかし、私はまた、ダイアログボックスウィンドウのインスタンスを取得する必要があります。私はハンドル –

+2

+1を使って得ることができないことを私は読んだ。'ShowMessage'(Dialogs)はウィンドウクラス' TMessageForm'を作成します。また、 'CBTProc'に' Result:= CallNextHookEx'を呼び出す必要があるとも思います。 – kobik

+1

'#32770'クラスは' MessageBox'(Windows)経由で作成されます。 – kobik

5

また、(OnDestroyでアンインストール)メインフォームのOnCreateイベントにインストールされたアプリケーション全体のフックを使用することができます。

procedure TMainForm.FormCreate(Sender: TObject); 
begin 
    ... 
    Application.HookMainWindow(ApplicationHook); 
end; 

procedure TMainForm.FormDestroy(Sender: TObject); 
begin 
    ... 
    Application.UnhookMainWindow(ApplicationHook); 
end; 

function TMainForm.ApplicationHook(var Message: TMessage): Boolean; 
var 
    I: Integer; 
begin 
    Result := False; 
    if (Message.Msg = WM_ENABLE) and not TWMEnable(Message).Enabled then // disabling 
    for I := 0 to Screen.FormCount - 1 do 
     with Screen.Forms[I] do 
     if Enabled and (ClassNameIs('TMessageForm') or // ShowMessage, MessageDlg 
      ClassNameIs('TForm') or // InputQuery 
      ClassNameIs('TMyLoginDialog')) then // your own dialogs, etc. 
     begin 
      Screen.Forms[I].Position := poScreenCenter; // for example 
      Result := True; 
      Break; 
     end; 
end; 
+0

これは現代のDelphiで動作するかどうかはわかりません。現代のDelphiでは、 'ShowMessage'は標準的なウィンドウのメッセージボックスであり、' TForm'の子孫ではありません。しかし、 'TForm'をフックしたいなら、このコードは良く見えます。 –

+0

@DavidHeffernan in Delphi XE2: 'ShowMessage'と' MessageDlg'はまだ 'TMessageForm'を使います。あなたはおそらく 'MessageBox' APIを意味します。これは 'Screen.Forms'には含まれないので、この場合には別の戦略が必要です。 –

+0

ああ、それはOSによって異なります。 Windows v6以降ではそうではありません。私はあなたがXP上で動作していると推測します。 –

0

TApplication.OnModalBeginTApplicationEvents.OnModalBeginがあります。私は実際にそれらを試していないので、あなたはこれらのイベントの中で所有者やモーダルフォームを取得できるかどうかについてコメントすることはできません。

2

なぜOnActiveFormChangeを使用しないのですか?

procedure TForm3.FormCreate(Sender: TObject); 
begin 
    Screen.OnActiveFormChange := ScreenActiveFormChange; 
end; 

procedure TForm3.ScreenActiveFormChange(Sender: TObject); 
begin 
    if Screen.ActiveForm is TOKRightDlg then 
    Screen.ActiveForm.Caption := 'Found'; 
end; 

procedure TForm3.Button1Click(Sender: TObject); 
begin 
    with TOKRightDlg.Create(nil) do 
    try 
    ShowModal; 
    finally 
    Free; 
    end; 
end; 
関連する問題