获取对话框窗口表单的引用(ShowMessage,MessageDialog等)

时间:2012-03-09 09:50:44

标签: delphi events

我可以使用任何事件,所以我会抓住屏幕上出现ShowMessage的那一刻吗?我还需要传递对显示消息的TForm的引用。

到目前为止,我尝试了OnDeactivate,但似乎ShowMessage并没有导致它......

在.NET中,应用程序上有一个方法可以捕获每个MessageBox(Application.AddFilterMessage或者像这样),我在delphi中需要这样的东西

我想要实现的目标是: 我必须抓住一个对话窗口出现的时刻(或者只是一个模态窗口,但它并不那么舒服)。我需要做几个指令。这些说明的目标是给我一个刚刚收到的DialogWindow的参考,以便我可以获得一些位于其上的按钮。

4 个答案:

答案 0 :(得分: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上,类名称为TMessageForm,因为该对话框实际上是Delphi TForm。但是,在Vista上以后,对话框是一个标准的窗口消息框对话框,窗口类名为#32770

我已经向ShowMessage发出了一次调用,但是如果要挂钩应用中显示的所有消息对话框,可以在启动时安装它。

答案 1 :(得分:5)

您还可以使用主窗体OnCreate事件中安装的应用程序范围的挂钩(已在OnDestroy中卸载):

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;

答案 2 :(得分: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;

答案 3 :(得分:0)

TApplication.OnModalBeginTApplicationEvents.OnModalBegin。我还没有真正尝试过,所以我无法评论你是否可以在这些活动中获得所有者和/或模态形式。