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.