Delphi: Detect when a new form has been created

匆匆过客 提交于 2019-12-01 23:02:02

You can use the SetWindowsHookEx function to install a WH_CBT Hook, then you must implement a CBTProc callback function and finally intercept one of the possible code values for this hook. in this case you can try with HCBT_ACTIVATE or HCBT_CREATEWND.

Check this sample for the HCBT_ACTIVATE Code.

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.

Note : if you uses the HCBT_CREATEWND code instead you will intercept any window created by the system not just "forms".

NGLN

Track Screen.CustomFormCount in 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;

Native dialogs managed and shown by Windows (TOpenDialog, TFontDialog, etc...) are created apart from the VCL and to track them also, you need a hacking unit. Try this one then.

oxo

Thanks to David I found a solution: The clue is to replace Screen.AddForm method with your own. The way how to do it is described in these SO answers:

Thanks again!

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!