3

我想检测何时创建了新表单。

现在我使用该Screen.ActiveFormChange事件并检查新表单,Screen.CustomForms但在表单事件ActiveFormChange之后被触发OnShow

我想在OnShow被解雇之前检测到表格。有没有办法在不修改Vcl.Forms单元的情况下做到这一点?

我想检测所有表单(还有 Delphi 模态消息等),因此无法从自定义类继承所有表单(如果我错了,请纠正我)。

或者,是否可以检测到某个TComponent.FComponents列表中添加了新组件?

4

3 回答 3

4

您可以使用该SetWindowsHookEx函数安装一个WH_CBTHook,然后您必须实现一个CBTProc 回调函数并最终截获该钩子的可能代码值之一。在这种情况下,您可以尝试使用HCBT_ACTIVATEor HCBT_CREATEWND

检查此示例以获取HCBT_ACTIVATE代码。

var
 hhk: HHOOK;

function CBT_FUNC(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
const
  ClassNameBufferSize = 1024;
var
 hWindow: HWND;
 RetVal : Integer;
 ClassNameBuffer: Array[0..ClassNameBufferSize-1] of Char;
begin
   Result := CallNextHookEx(hhk, nCode, wParam, lParam);
   if nCode<0 then exit;
   case nCode of
     HCBT_ACTIVATE:
     begin
       hWindow := HWND(wParam);
       if (hWindow>0) then
       begin
          RetVal := GetClassName(wParam, ClassNameBuffer, SizeOf(ClassNameBuffer));
          if RetVal>0 then
          begin
            //do something  
            OutputDebugString(ClassNameBuffer);                     
          end;
       end;
     end;
   end;

end;

Procedure InitHook();
var
  dwThreadID : DWORD;
begin
  dwThreadID := GetCurrentThreadId;
  hhk := SetWindowsHookEx(WH_CBT, @CBT_FUNC, hInstance, dwThreadID);
  if hhk=0 then RaiseLastOSError;
end;

Procedure KillHook();
begin
  if (hhk <> 0) then
    UnhookWindowsHookEx(hhk);
end;

initialization
  InitHook();

finalization
  KillHook();

end.

注意:如果您改用HCBT_CREATEWND代码,您将拦截系统创建的任何窗口,而不仅仅是“表单”。

于 2012-07-20T17:08:20.170 回答
2

跟踪:Screen.CustomFormCount_Application.OnIdle

  private
    FPrevFormCount: Integer;
  end;

procedure TForm1.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
begin
  if Screen.CustomFormCount > FPrevFormCount then
    Caption := Caption + ' +1';
  if Screen.CustomFormCount <> FPrevFormCount then
    FPrevFormCount := Screen.CustomFormCount;
end;

procedure TForm1.TestButton1Click(Sender: TObject);
begin
  TForm2.Create(Self).Show;
end;

procedure TForm1.TestButton2Click(Sender: TObject);
begin
  ShowMessage('Also trackable?');  // Yes!
end;

procedure TForm1.TestButton3Click(Sender: TObject);
begin
  OpenDialog1.Execute; // Doesn't update Screen.CustomFormCount
end;

由 Windows 管理和显示的本机对话框(TOpenDialogTFontDialog等...)是在 VCL 之外创建的,并且为了跟踪它们,您需要一个黑客单元。那就试试这个吧。

于 2012-07-20T11:26:51.637 回答
1

感谢大卫,我找到了一个解决方案:线索是Screen.AddForm用你自己的方法替换方法。这些SO答案中描述了如何做到这一点:

再次感谢!

于 2012-07-20T16:35:16.697 回答