2012-10-23 11 views
6

Ich habe eine Komponente von Drittanbietern, die ein Druckvorschauformular anzeigt. Ich möchte die Beschriftung des Vorschauformulars in etwas geeigneteres ändern. Leider habe ich nicht die Quelle für die Drittanbieter-Komponente und die Komponente bietet nicht die Funktionalität.Wie kann ich die Beschriftung eines modalen Formulars ohne Zugriff auf die Quelle ändern?

Ist es möglich, irgendwie das modale Formular zu fangen, wie es ist, angezeigt wird, und legen Sie es Eigenschaften ist, bevor es angezeigt wird?

+4

Ein weiteres Beispiel, warum Sie niemals Komponenten von Drittanbietern verwenden sollten, für die Sie keine Quelle haben, wenn eine Option verfügbar ist, um sie zu erhalten. :-) Sie können angeben, welche Komponente von Drittanbietern Sie verwenden, damit eine Person, die eine bekannte Lösung für diesen Komponentensatz besitzt, diese bereitstellen kann. –

+2

@Ken: TeeChart. Ich könnte auf die 'with source'-Version upgraden, aber es ist schwer, ein Minimum von 250 Dollar zu rechtfertigen, nur um die Überschrift eines Formulars zu ändern: o) – norgepaul

+0

Das Problem ist, wenn sich etwas ändert (oder TeChart im nächsten nicht mehr enthält) Version von Delphi), kann Ihr gesamter Code, der ihn verwendet, nicht in die nächste Version des Compilers verschoben werden. Wenn Sie Code haben, der von Komponenten Dritter abhängt, benötigen Sie die Quelle, um sich in Zukunft zu schützen. Es ist eines der allerersten Dinge, die Sie nach dem Erlernen von Delphi lernen sollten - seine offene Architektur eignet sich hervorragend für Erweiterungen von Drittanbietern, aber wenn Sie keine Quellen erhalten, werden Sie lahm gelegt, wenn sich die Dinge in Zukunft ändern. –

Antwort

10

Das modale Formular bewirkt, dass das aufrufende Formular deaktiviert wird. Sie können auf dem Formular, das aktiv ist, bevor das modale Formular angezeigt wird, auf Nachrichten WM_ACTIVATE warten. Sie haben das Handle des Aktivierungsfensters im Message-Handler, Sie können das testen, wenn es eine Form vom Typ des modalen Formulars hat. Im Folgenden finden Sie Beispiele für den Klassennamen, den Sie mit etwas wie Spy ++ erhalten können. Beachten Sie, dass die Deaktivierung kurz nach dem Anzeigen des modalen Formulars erfolgt, aber ich denke nicht, dass es möglich wäre, die unterschiedliche Beschriftung zu bemerken.

type 
    TForm1 = class(TForm) 
    .. 
    protected 
    procedure WMActivate(var Message: TWMActivate); message WM_ACTIVATE; 
    end; 

procedure TForm1.WMActivate(var Message: TWMActivate); 
var 
    Form: TWinControl; 
begin 
    if Message.Active = WA_INACTIVE then begin 
    Form := FindControl(Message.ActiveWindow); 
    if Form is TCustomForm then begin 
     if TCustomForm(Form).ClassName = 'TThirdPartyModalForm' then 
     TCustomForm(Form).Caption := 'My caption'; 
    end; 
    end; 
    inherited; 
end; 
+1

Funktioniert perfekt. Danke Sertac. – norgepaul

+1

Was ist mit dem 'TScreen.OnActiveFormChange' Ereignisse mit der' TScreen.ActiveCustomForm' oder 'TScreen.ActiveForm' Eigenschaft, statt' Umgang mit WM_ACTIVATE' direkt und für den aktiven 'TForm' gesucht? –

+0

@Remy - Es wird nur ein wenig später ausgelöst, wenn das modale Formular während der Fokusänderung aktiviert wird, sollte es in Ordnung sein. Aber FindControl ist ziemlich schnell, wenn es das Problem ist, in der Tat wird es während Application.ProcessMessage mit jeder eingereihten Nachricht aufgerufen. –

2

Sie können einen WH_CBT Haken mit der SetWindowsHookEx Funktion installieren.

var 
hhk: HHOOK; 


function CBT_FUNC(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; 
const 
    ClassNameBufferSize = 1024; 
var 
hTemp : HWND; 
i  : Integer; 
RetVal : Integer; 
ClassNameBuffer: Array[0..ClassNameBufferSize-1] of Char; 
begin 
    case nCode of 
    HCBT_ACTIVATE: 
    begin 
     hTemp := HWND(wParam); 
     if (Screen<>nil) and (hTemp>0) then 
     begin 
      RetVal := GetClassName(wParam, ClassNameBuffer, SizeOf(ClassNameBuffer)); 
      //check for the class 
      if (RetVal>0) and SameText(ClassNameBuffer,'TForm2') then 
      begin 
      Assert(RetVal < ClassNameBufferSize, 'Class name larger than fixed buffer size'); 
      for i := 0 to Screen.FormCount-1 do 
      if Screen.Forms[i].Handle=hTemp then 
       begin 
        //set the caption 
        Screen.Forms[i].Caption:='Hello'; 
        Break; 
       end; 
      end; 
     end; 
    end; 
    end; 
    Result := CallNextHookEx(hhk, nCode, wParam, lParam); 
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. 
2

ist hier ein "Pseudo" Code, den Sie (nicht getestet) versuchen könnte:

const 
    MY_PRINT_PREVIEW_MSG = WM_USER + 200; 

type 
    TForm1 = class(TForm) 
    procedure MyPrintPreviewMsg(var Msg: TMessage); message MY_PRINT_PREVIEW_MSG; 
    procedure MyPrintPreview; 
    end; 
... 
procedure TForm1.MyPrintPreviewMsg(var Msg: TMessage); 
var 
    h: HWND; 
begin 
    h := Screen.Forms[0].Handle; // if the modal dialog is VCL dialog (verify it with spy++) 
    // h := FindWindow(<class name>, <caption>); // non VCL window 
    if (h <> 0) then 
    begin 
    SetWindowText(h, 'new caption'); 
    end; 
end; 

procedure TForm1.MyPrintPreview; 
begin 
    PostMessage(Handle, MY_PRINT_PREVIEW_MSG, 0, 0); 
    ThirdPartyPrintPreview; 
end; 
6

Versuchen Sie es mit dem TScreen.OnActiveFormChange Ereignis, das TScreen.ActiveCustomForm oder TScreen.ActiveForm Eigenschaft verwenden zu wissen, welche TForm den Fokus hat:

procedure TMainForm.DoSomething; 
begin 
    Screen.OnActiveFormChange := ActiveFormChanged; 
    try 
    // do something that triggers the modal form ... 
    finally 
    Screen.OnActiveFormChange := nil; 
    end; 
end; 

procedure TMainForm.ActiveFormChanged(Sender: TObject); 
var 
    Form: TCustomForm; 
begin 
    Form := Screen.ActiveCustomForm; 
    if (Form <> nil) and (Form.ClassName = 'TModalFormClassName') then 
    Form.Caption := 'My caption'; 
end; 
Verwandte Themen