Delphi 获取对对话框窗口窗体(ShowMessage、MsgDialog等)的引用
是否有任何事件可供我使用,以便我能够捕捉屏幕上出现Delphi 获取对对话框窗口窗体(ShowMessage、MsgDialog等)的引用,delphi,events,Delphi,Events,是否有任何事件可供我使用,以便我能够捕捉屏幕上出现ShowMessage的时刻?我还需要传递一个对显示消息的TForm的引用 到目前为止,我尝试了OnDeactivate,但似乎,ShowMessage并没有引起它 在.NET中,应用程序上有一种方法可以捕获每个MessageBox(Application.AddFilterMessage或类似的smth),我需要在delphi中使用类似的方法 我想要实现的是: 我必须抓住一个对话框窗口出现的时刻(或者只是一个模式窗口,但它不是那么舒服)。那么我
ShowMessage
的时刻?我还需要传递一个对显示消息的TForm
的引用
到目前为止,我尝试了OnDeactivate
,但似乎,ShowMessage
并没有引起它
在.NET中,应用程序上有一种方法可以捕获每个MessageBox(Application.AddFilterMessage或类似的smth),我需要在delphi中使用类似的方法
我想要实现的是:
我必须抓住一个对话框窗口出现的时刻(或者只是一个模式窗口,但它不是那么舒服)。那么我需要做几个指示。这些说明的目的是让我参考刚刚收到的DialogWindow,例如,我可以在上面找到一些按钮。在现代Delphi版本中,在现代Windows版本中,
ShowMessage
会生成一个Windows对话框窗口。您可以使用WH\u CBT
hook捕捉该对话框窗口的激活
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
,因为该对话框实际上是一个DelphiTForm
。但是,在Vista和更高版本上,该对话框是一个标准窗口消息框对话框,窗口类名为#32770
我已经展示了一个对
ShowMessage
的调用,但是如果你想挂接应用程序中显示的所有消息对话框,你可以在启动时安装它。你也可以使用安装在主窗体的OnCreate
事件中的应用程序范围的钩子(在OnDestroy
中卸载):
有和。我还没有真正尝试过它们,所以我无法评论您是否可以在这些事件中获取所有者和/或模态表单。为什么不直接使用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;
事实上,我想隐藏我的应用程序中显示的所有消息。但是我还需要得到dialogbox窗口的一个实例。我已经读到,我无法使用手柄+1获取它
ShowMessage
(对话框)创建一个窗口类TMessageForm
。我还认为您需要在CBTProc
中调用Result:=CallNextHookEx
。\32770类是通过MessageBox
(Windows)创建的。@jacekwiecieńhook proc中的wnd
局部变量是被激活窗口的句柄。@David Heffernan我意识到这可能是一个不切实际的问题。我用一个表单创建了一个测试项目。我想把我所有的通讯都挂上。我应该把函数CBTProc放在哪里?虽然David的代码可能会满足您的需求,但我的第一个想法是,您可能正在寻找解决某些问题的方法。可能有更好的方法,这取决于你为什么需要这样做。这是一个调试步骤,一个解决错误的第三方控制、测试程序或其他问题的方法吗?也许你可以使用or?@UlrichGerhardt我相信这是最好的答案,适用于(显然)Delphi 2010及更高版本。在第一次测试后,OnModalBegin看起来很有希望。你应该把它作为答案发布,以防我让它工作:)OnModalBegin不错,但它不会捕获显示windows对话框的直接调用,也不会让事件处理程序知道任何有关正在激活的模式表单的信息。我不确定这是否适用于现代Delphi。在现代Delphi中,ShowMessage
生成一个标准窗口消息框,而不是TForm
的后代。但是如果你想钩住一个t表单
,那么这个代码看起来不错。@Delphi XE2中的DavidHeffernan:ShowMessage
和MessageDlg
仍然使用TMessageForm
。您可能是指MessageBox
API。这不会包含在屏幕表单中,因此您需要针对这种情况使用不同的策略。啊,这取决于操作系统。在WindowsV6及更高版本上,情况并非如此。我想你是在XP上运行的。@DavidHeffernan我是在Windows7 Ultimate 64位上运行的。你是在运行WindowsClassic主题吗?你只需要阅读代码就可以看到发生了什么。如果要转换,请查找。检查(6)并在Vcl.Dialogs.pas
中使用最新的CommonDialogs
。目前,您的代码在某些情况下无法工作。
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;