3

新しいフォームがいつ作成されたかを検出したいと思います。

今、私はScreen.ActiveFormChangeイベントを使用して新しいフォームをチェックしますScreen.CustomFormsが、フォームのイベントのActiveFormChange後に発生します。OnShow

OnShow解雇される前のフォームも検出したいです。Vcl.Formsユニットを変更せずにこれを行う方法はありますか?

すべてのフォーム (Delphi モーダル メッセージなども) を検出したいので、カスタム クラスからすべてのフォームを継承することはできません (間違っている場合は修正してください)。

または、新しいコンポーネントがいくつかのTComponent.FComponentsリストに追加されたことを検出することは可能ですか?

4

3 に答える 3

4

この関数を使用してフックSetWindowsHookExをインストールできます。次に、 CBTProcコールバック関数を実装し、最後にこのフックの可能なコード値の1つをインターセプトする必要があります。この場合、またはで試すことができます。WH_CBTHCBT_ACTIVATEHCBT_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

David のおかげで解決策が見つかりました。手がかりは、Screen.AddFormメソッドを独自のものに置き換えることです。それを行う方法は、これらの SO 回答で説明されています。

再度、感謝します!

于 2012-07-20T16:35:16.697 に答える