Einzelnen Beitrag anzeigen

peterbelow

Registriert seit: 12. Jan 2019
Ort: Hessen
701 Beiträge
 
Delphi 12 Athens
 
#2

AW: Verwendung von TTitleBarPanel mit ModalPopupMode := pmAuto

  Alt 21. Mär 2024, 13:06
Bei der Verwendung von TTitleBarPanel in Forms, die mit ShowModal aufgerufen werden, ist mir ein merkwürdiges Verhalten aufgefallen. Wenn Application.ModalPopupMode := pmAuto gesetzt ist (was ja bei neueren Delphi-Anwendungen standardmäßig der Fall ist), wird die Custom Titlebar beim zweiten Aufruf des Fensters nicht über die normale Titlebar gezeichnet, sondern darunter, als wäre sie nicht richtig zugewiesen (siehe Anhang). Beim ersten Aufruf des Fensters sieht alles korrekt aus.

Reproduzieren lässt sich der Fehler mit zwei Forms und einer Titlebar in Form2. Die Titlebar wird über  CustomTitlebar.Control := TitleBarPanel1 und CustomTitlebar.Enabled := True in Form2 zugewiesen. Öffnet man über den Button in Form1 nun Form2, schließt Form2 wieder und öffnet es dann nochmal, tritt der Fehler wie auf dem Bild auf.

Wenn unter TForm2.FormActivate die API-Methode SetWindowPos mit dem Parameter SWP_FRAMECHANGED aufgerufen wird, tritt das Problem nicht mehr auf. In komplexeren Fenstern führt das aber zu einem unschönen Flackern. Gibt es einen eleganteren Weg, den Fehler zu umgehen oder handelt es sich dabei um einen Bug in Delphi? pmAuto führt generell an verschiedenen Stellen zu Problemen (siehe https://stackoverflow.com/questions/...bug-workaround), was auch so in der Dokumentation steht, wird aber in unserer Anwendung benötigt, damit TCommonDialoge, sowie die dynamische Vorschau in der Windows-Taskleiste korrekt funktionieren.
Es ist wohl ein Bug aber der beste workaround wäre meiner Meinung nach, modal genutzte Forms nicht in die autocreate-Liste aufzunehmen sondern nach Bedarf zu erzeugen und danach auch sofort wieder zu zerstören. Man braucht dann auch keine Form-Variable, die läßt sich sozusagen "internalisieren" wenn man der Formklasse eine public class function nach dem folgenden Muster spendiert:

Delphi-Quellcode:
class function TFormXYZ.Execute(aFormdata: TFormXYZData): boolean;
var
  LInstance: TFormXYZ;
begin
  LInstance := TFormXYZ.Create(nil);
  try
    LInstance.Initialize(aFormData);
    Result := LInstance.ShowModal := mrOK;
    if Result then
      LInstance.GetUserInput(aFormData);
  finally
    LInstance.Free;
  end;
end;
TFormXYZData ist dabei ein Objekt das die Daten enthält, die das Form anzeigen bzw. entgegennehmen soll. Man kann auch einen record verwenden, dann muß der Parameter für Execute aber ein Var-Parameter sein.

Auf diese Weise kommt man auch nicht in Versuchung, eine Form als Datenspeicher zu mißbrauchen.
Peter Below
  Mit Zitat antworten Zitat