我可以使用任何事件,所以我会抓住屏幕上出现ShowMessage
的那一刻吗?我还需要传递对显示消息的TForm
的引用。
到目前为止,我尝试了OnDeactivate
,但似乎ShowMessage
并没有导致它......
在.NET中,应用程序上有一个方法可以捕获每个MessageBox(Application.AddFilterMessage或者像这样),我在delphi中需要这样的东西
我想要实现的目标是: 我必须抓住一个对话窗口出现的时刻(或者只是一个模态窗口,但它并不那么舒服)。我需要做几个指令。这些说明的目标是给我一个刚刚收到的DialogWindow的参考,以便我可以获得一些位于其上的按钮。
答案 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.OnModalBegin和TApplicationEvents.OnModalBegin。我还没有真正尝试过,所以我无法评论你是否可以在这些活动中获得所有者和/或模态形式。