Form mit selbstgemachtem TitleBar

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Antworten
Benutzeravatar
Winni
Beiträge: 980
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.0.12, fpc 3.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Form mit selbstgemachtem TitleBar

Beitrag von Winni »

Hallo!

Im internationalen Forum tauchte die Frage auf, ob man einen Button (oder andere Komponenten) in dem TitleBar unterbringen kann.

Das ist ein wundes Thema bei Lazarus.
Unter Windows kommt man per API-Calls mühselig an den TitleBar ran.
Unter Linux ist da keine Chance, da der TitleBar "Eigentum" des Window-Managers ist, der zum Desktop gehört und nicht zu Lazarus.

Da muss man sich ein Workaround schnitzen.
Mit BorderStyle = bsNone wird der TitleBar unsichtbar.

Mit einem Panel oben in der Form schnitzt man sich selber einen.
Darauf kommt ein Timage, in das die verschieden Icon-Sets für das System-Menü geladen werden können.
Da könnte dann auch der gewünschte Button hin.

Die Demo hat die Möglichkeit für 6 verschiedene Icon-Sets: 3 KDE und 3 Windows.

Screenshot und Project anbei.

Winni
Dateianhänge
NoTitleBar.png
NoTitleBar.png (36.25 KiB) 701 mal betrachtet
NoTitleBar.zip
(198.14 KiB) 27-mal heruntergeladen

kirchfritz
Beiträge: 91
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 2.0.2 FPC 3.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Form mit selbstgemachtem TitleBar

Beitrag von kirchfritz »

Ein paar dumme Fragen seien erlaubt:

1) Welche Bedeutung hat das rote Rectangle das im FormPaint Ereignis gezeichnet wird?

Code: Alles auswählen

procedure TForm1.FormPaint(Sender: TObject);
var R : TRect;
begin
Canvas.Pen.Color := clRed;
R := Rect(1,1,width-1,Height-1);
Canvas.Rectangle (R);

end;  
Ich denke, das Rectangle soll die Fenstergröße veranschaulichen, die durch den borderStyle=bsNone verloren gegangen ist.

Schon stellt sich die zweite Frage:
2. Warum wird das rectangle mit

Code: Alles auswählen

Rect(1,1,width-1,Height-1);
gezeichnet und nicht mit

Code: Alles auswählen

Rect(0,0,width,Height);
3. und viel interessantere Frage :
Wie gedenkst Du das FormResizing zu realisieren?

4.Frage: Was passiert im FormCreate Ereignis?

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
var
    x,xy, xyDest,i : Integer;
    R : Trect;
    ICur : TBGRAIconCursor;
    MemStream: TMemoryStream;
    bmp : TBGRABitmap;
begin
  // Icon
  ICur := TBGRAIconCursor.Create;
  MemStream:= TMemoryStream.Create;
  Application.Icon.SaveToStream(MemStream);
  MemStream.Position:=0;
  ICur.LoadFromStream(MemStream);
  bmp := TBGRABitmap.Create;
  BGRAreplace (bmp, ICur.GetBitmap(0));
  xy := Image1.Height;
  BGRAreplace (bmp,bmp.resample(xy,xy));
  bmp.draw(Image1.Canvas,0,0,false);
  bmp.free;
  ICur.Free;
  MemStream.free;



  (*
  xy := application.Icon.Height;
  tmp := TBGRAbitmap.Create (xy,xy);
  R := Rect(0,0,xy,xy);
  tmp.Canvas.CopyRect (R,application.Icon.Canvas,R);
  xyDest := Image1.Height;
  BGRAreplace (tmp,tmp.resample(xyDest,xyDest));
  tmp.Draw(Image1.canvas,0,0);
  tmp.free;
  *)
  showTBarIcons;
  for i := 0 to high(Inames) do
    Icons.Items.add (Inames[i]);
  Icons.ItemIndex := 0;
  SelectIconSet (0);
end;        
Ohne Kommentare kann ich die beabsichtigten "Features" nicht herauslesen. Wäre hilfreich, wenn Du erwartest, dass jemand verstehen soll, was da passiert.
Zum Beispiel mit einem TBGRAIconCursor habe ich bisher noch nie gearbeitet. Ich weiss gar nicht wozu der gut sein soll.
Dann wird das Application Icon in einen MemStream geladen, und der memStream vom TBGRAIcoCursor wieder gelesen.
Dann wird auch noch eine TBGRABitmap erzeugt und "verwurschtelt". (Sorry für meine Ausdrucksweise)
Das ist mir alles zu rätselhaft, mit Kommentaren könnte man besser verstehen, was Du dem Quellcodeleser sagen willst.
Vor allem: Was hat das mit dem Thema "selbstgemachte Titlebar" zu tun?

Hoffentlich bist Du mir wegen meiner dummen Fragen nicht böse.
Ich finde das Thema "Form mit selbstgemachtem Titlebar" wunderschön und sehr interessant.
Aber die Lösung mit borderstyle=bsNone und selbst gezeichnetem Panel als Titlebar ist auch nicht gerade neu, wenn Du ehrlich bist.
Und Dein Quellcode hat für mich zu viele Rätsel

Nix für ungut
Fritz

Benutzeravatar
Winni
Beiträge: 980
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.0.12, fpc 3.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Form mit selbstgemachtem TitleBar

Beitrag von Winni »

Hi!

Zu Deinen Fragen:

Code: Alles auswählen

Rect(1,1,width-1,Height-1);
ist notwenig: Bei BorderStyle = bsNone zeigt er keinen TitleBar mehr an, es geht aber auch die Border flöten - daher der Name. Muss man also selbst zeichnen.

Und das (+1,+1,-1,-1) mach ich weil das einen schöneren Rand ergibt: 1 Pixel Form, dann 1 Pixel Border, dann der Rest der Form.
"Design für Arme" kann man das auch nennen.

FormCreate macht Folgendes:

Ich lutsche das Icon der Application (Projecteinstellungen, erste Seite) per Memorystream in eine BGRAIconCursor.
Dann hole ich die BGRABitmap aus dem BGRAIconCursor und bringe es auf das richtige Format. Dann male ich die Bitmap links oben auf das Image in dem selbstgemachten Taskbar.
Könnte man auch alles mit TBitmap und TIcon machen, aber ich hatte gerade kein vernünftges resize zur Hand. Und das fällt bei BGRAbitmap aus der Tüte.

Ansonsten: Beim resize kümmern sich die richtigen Anchors um das Taskbar-Panel und de Elementen da drauf. Da kümmert sich PanelOnpaint nur noch um die Caption - immer scön zentriert.

Ausreichend Antwort??

Winni

kirchfritz
Beiträge: 91
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 2.0.2 FPC 3.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Form mit selbstgemachtem TitleBar

Beitrag von kirchfritz »

Ausreichend Antwort.

Zur Abwechslung ein bißchen Lob, weil ja scheinbar niemand das Demo-Projekt von Dir kommentiert hat:

1. Sehr interessant finde ich das Feature, das die FontFarbe der Titlebar abhängig von der Farbe der Titlebar gesetzt wird

Code: Alles auswählen

Panel1.Color := img.GetPixel(0,0);
col:= img.GetPixel(0,0);
if col.red+col.green+col.blue < 200 then 
    Panel1.Canvas.Font.Color := clWhite 
else
    Panel1.Canvas.Font.Color := clBlack; 
2. Weiters sehr interessant ist die Technik, mit der das Verschieben der MainForm realisert wurde (Weil ja kein Fenstertitel da ist, kann man darüber auch das Fenster nicht verschieben).
Man merkt sich beim MouseDown, wo man hingeklickt hat...
...und beim MouseMove verschiebt man dann entsprechend das ganze Fenster.

Code: Alles auswählen

procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;
	 Shift: TShiftState; X, Y: Integer);
begin
   if ssLeft in Shift then 
   begin 
      xoff := x; 
      yOff := y; 
   end;
end;

procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
	 Y: Integer);
begin
   if ssLeft in Shift then
   begin
      left := Left+x -Xoff;
      top := top +y - yoff;
   end;
end;

Die Frage aus dem internationalen Forum, ob man einen Button in der Titlebar unterbringen kann, hast Du aber bis jetzt nicht beantwortet.
Das Demo-Projekt zeigt lediglich, wie eine Grafik in die Titlebar platziert wird.
Aber wie man einen Button auf ein Panel setzt, sollte jeder Lazarus-Anwender beherrschen, das wäre eigentlich nicht erklärungsbedürftig, oder siehst Du hier ein Problem?

Vielleicht erweitert jemand das Demo-Programm um die Möglichkeit, die Formgröße mit der Mouse zu verändern, durch Anpacken und Ziehen an den FormRändern?

Viele Grüße
Fritz

Benutzeravatar
Winni
Beiträge: 980
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.0.12, fpc 3.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Form mit selbstgemachtem TitleBar

Beitrag von Winni »

Hallo!

Danke für die Blumen!

ad 1: Ja, das ist "poor mans lightnig". Igendwas muss da ja gemacht werden, bevor schwarze Buchstaben auf duunkelgrauem Hintergrund stehen. Korrekt wäre die Berechnung unter Einbeziehung der Leuchtkraft der einzelnen Farben gewesen, aber ist ja nur ne Demo.

ad 2: Das hab ich gelernt, als ich (noch unter Delphi) probiert habe, wie man einer Form eine beliebige Form (mittels Polygon) geben kann. Die haben dann auch keinen TitleBar mehr. Und man muss sie ja bewegen können.

Das Plazieren von einem Button auf dem TitleBar-Panel sollte ja nun trivial sein.

Da ich mich aber seit den frühen X-Server-Tagen und Win 3.1 über das Gefummel an den Rändern zum Resizen ärgere, hätte ich aber einen anderen Vorschlag: Zwei SpinEdits um die Größe der Form in X- und Y-Richtung zu ändern. Auf dem neuen TitleBar.

Auch graphisch kann man recht einfach zuschlagen: z.B. einen Farbverlauf in das PanelOnpaint zaubern (Canvas.GradientFill).

Winni

Benutzeravatar
Winni
Beiträge: 980
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.0.12, fpc 3.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Form mit selbstgemachtem TitleBar

Beitrag von Winni »

Hi!

Ich hab dann mal meine Idee umgesetzt:

SpinEdits für Breite und Höhe der Form im TitleBar.

Project und Screenshot anbei

Winni
Dateianhänge
NoTitleBarSpins.png
NoTitleBarSpins.png (36.99 KiB) 501 mal betrachtet
NoTitleBar01.zip
(229.73 KiB) 25-mal heruntergeladen

kirchfritz
Beiträge: 91
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 2.0.2 FPC 3.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Form mit selbstgemachtem TitleBar

Beitrag von kirchfritz »

Ich habe einen hervorragenden Artikel gefunden, wie man unter Delphi eine "Form mit selbstgemachtem Titlebar" erstellt.
Siehe hier: https://medium.com/@vuio/delphi-borderl ... 2538e3ec48
Den darin enthaltenen Delphi-Quellcode konnte ich in Delphi kompilieren und das Programm zeigt das im Artikel beschriebene Verhalten.
Als Lazarus-Jünger habe ich dann versucht diesen Delphi-Quellcode in Lazarus/Freepascal zu übersetzen.
Ist mir gelungen (bitte kein Lob dafür).
Leider verhält sich das Lazarus-Programm nicht wie gewünscht.
Irgendwie wird die message WM_NCCALCSIZE nicht ausgelöst, deshalb wird die Titelbar nicht "weggepinselt" sondern bleibt beharrlich zu sehen.
Kann mir jemand erklären, warum sich mein Lazarus-Programm so anders als das Delphi-Programm verhält?
Dateianhänge
BorderlessForm3.zip
(127.17 KiB) 24-mal heruntergeladen

Antworten