有多种方式可以从 Delphi 程序中显示模态表单或对话框(VCL 或系统原生),因此您需要以某种方式挂钩到消息处理并捕获显示模态表单或对话框时发送的消息。
为此,可以使用API 函数设置消息挂钩。SetWindowsHookEx()
由于您仅在应用程序处于非活动状态时才需要它,您可以在应用程序事件的处理程序中设置它OnDeactivate
,并在应用程序事件的处理程序中将其重置OnActivate
:
var
gNextHook: HHOOK;
procedure TForm1.AppActivate(Sender: TObject);
begin
if gNextHook <> 0 then
UnhookWindowsHookEx(gNextHook);
gNextHook := 0;
end;
procedure TForm1.AppDeactivate(Sender: TObject);
begin
gNextHook := SetWindowsHookEx(WH_CALLWNDPROC, @WndProcHook, 0,
GetCurrentThreadId);
end;
钩子函数将监视显示模式对话框或表单时发送的消息,并FlashWindowEx()
使用正确的参数调用:
function WndProcHook(nCode: integer; AWParam: WPARAM; ALParam: LPARAM): LRESULT; stdcall;
var
DataPtr: PCWPStruct;
Fwi: TFlashWInfo;
begin
DataPtr := PCWPStruct(ALParam);
if (DataPtr^.message = WM_INITDIALOG)
or ((DataPtr^.message = CM_ACTIVATE) and (DataPtr^.lParam = 0) and (DataPtr^.wParam = 0))
then begin
Fwi.cbSize := SizeOf(TFlashWInfo);
// flash caption of new modal window
Fwi.hwnd := DataPtr^.hwnd;
Fwi.dwFlags := FLASHW_ALL or FLASHW_TIMERNOFG;
Fwi.uCount := 0;
Fwi.dwTimeout := 0;
FlashWindowEx(Fwi);
// uncomment this to flash task bar button as well
(*
Fwi.hwnd := Application.MainForm.Handle;
Fwi.dwFlags := FLASHW_TRAY or FLASHW_TIMERNOFG;
FlashWindowEx(Fwi);
*)
end;
Result := CallNextHookEx(gNextHook, nCode, AWParam, ALParam);
end;
我选择了WM_INITDIALOG
为打开或保存对话框之类的本机对话框发送的内容,以及CM_ACTIVATE
在以模态方式显示 VCL 表单时发送的内容。可能有更多这样的消息需要被捕获。上面的代码适用于MessageDlg()
函数、Application.MessageBox()
函数和TOpenDialog
至少。
由于这些对话框没有自己的任务栏按钮,我添加了(注释掉)代码来刷新主窗体的任务栏按钮。这不是最佳的,因为它们不同步。
在 Windows XP 上使用 Delphi 2009 进行测试,省略了所有错误处理,仅将其用作起点。