Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Firemonkey Form Constraints (https://www.delphipraxis.net/184917-firemonkey-form-constraints.html)

Scurra 30. Apr 2015 09:50


Firemonkey Form Constraints
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen,

ich habe vor ein paar Wochen mein erstes kleines Programm mit Firemonkey geschrieben. Nun möchte ich verhindern, dass mein Formular unter eine bestimmte Größe verkleinert werden kann. Bei VCL gibt es dazu entweder die Property Constraints, mit der man die minimale Höhe und Breite festlegen kann oder man verwendet das OnCanResize-Event, um das Verändern der Größe zu verbieten, wenn man eine zu kleine Höhe oder Breite hat bzw. man setzt dort die neue Größe auf die minimal gewünschte Größe, falls die minimale Größe unterschritten wird.

In Firemonkey gibt es leider weder die Constraints für Formulare noch das OnCanResize-Event. Stattdessen habe ich im Internet ein paar andere Lösungen gesehen, die aber immer Nebeneffekte besitzen. Beispielsweise kann man das OnMouseUp-Event auslösen, wenn man die Größe mit der Maus zur Minimalgröße gezogen hat.
Eine andere Lösung, die ich im Moment verwende, ist, im OnResize-Event die Größe auf die Minimalgröße zu setzen, wenn die Minimalgröße unterschritten wird. Das führt jedoch natürlich zu einem flakerndem Formular, da die Größe zwei mal direkt hintereinander verändert wird, einmal durch die Maus und einmal durch das OnResize-Event selbst.

Hat jemand eine Idee, wie man das Problem mit möglichst geringem Aufwand beheben kann?

Anbei schicke ich noch ein Minimalbeispiel von meinem Problem.

Ich verwende im Moment Delphi XE8 Professional.

Gibt es evtl. noch ein Event, das vor dem OnResize-Event aufgerufen wird? Dann könnte ich dort versuchen, aus der Mausposition zu bestimmen, ob die Größe nach dem Resize-Event zu klein ist und dort schon reagieren, in dem ich die Größe auf die Minimalgröße setze.

Edit: Mir ist gerade aufgefallen, dass ich mich im Titel Vertippt habe: Es sollte natürlich "Form" und nicht "From" heißen.

Harry Stahl 1. Mai 2015 15:58

AW: Firemonkey From Constraints
 
Vielleicht kann man ja auch einen mix aus den beiden Ansätzen machen: Release der Maus, wenn einer der Minimalwerte (Breite oder Höhe) unterschritten ist und dann für diesen Wert - in einem Extra Thread - den Minimalwert setzen.

Im ResizeEvent kann man nach ReleaseCapture die angepassten Werte nicht setzen, da das Formular automatisch wieder auf die Ausgangsgröße zurückspringt, die es hatte, bevor man mit der Maus anfing, die Größe zu verändern. Selbst wenn man sich die Werte merkt und innerhalb des ResizeEvents nach ReleaseCapture setzt, geht es nicht. Daher kann man hier auf einen Task zugrückgreifen, der dann quasi in einem anderen Thread die Synchronisation mit dem Formular macht.

Kleiner Nachteil ist, dass der Anwender noch einmal mit der Maus ansetzen muss - wenn er eine Grenze unterschritten hat, z.B. die Breite - um dann den anderen Wert verändern zu können (z.B. dann die Höhe).

Jedenfalls flackert nichts mehr.

Delphi-Quellcode:
unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.Controls.Presentation, FMX.StdCtrls, FMX.Layouts,

  System.Threading ; // <------- wird hier wegen Task benötigt.

type
  TForm1 = class(TForm)
    procedure FormResize(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    procedure DoConstraints (NewWidth, NewHeight: Integer);
  end;

const
  MIN_WIDTH = 300;
  MIN_HEIGHT = 250;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.DoConstraints (NewWidth, NewHeight: Integer);
begin
  setbounds (left, top, NewWidth, NewHeight);
end;

procedure TForm1.FormResize(Sender: TObject);
var
  T: ITask;
  w, h: Integer;
begin
  if (width < MIN_WIDTH) or (height < Min_Height) then begin
    if width < Min_Width then w := Min_Width else w := Width;
    if height < Min_Height then h := Min_Height else h := Height;

    ReleaseCapture;
    T := TTask.Create(procedure ()
      begin
        TThread.Synchronize(
        nil,
        procedure
        begin
          Self.DoConstraints (w, h);
        end);
      end);
    T.Start;
  end;
end;

end.
Muss allerdings anmerken, dass ich kein großer Threading-Experte bin. Vielleicht kann einer, der das ist, hier ein paar hilfreiche Anmerkungen machen, ob man das anders machen muss oder besser lösen kann. Da das hier ja nur zu grundsätzlichen Demonstration ist, habe ich auf Try ... Except Konstrukte verzichtet.

Wenn man hier eine abschließende Lösung gefunden hat, würde es sich natürlich noch anbieten, eine Extra Prozedur dafür anzulegen, die man dann im ResizeEvent nur noch aufrufen braucht und somit wiederverwendbar in anderen Projekten einsetzen kann.

Scurra 4. Mai 2015 06:12

AW: Firemonkey From Constraints
 
Danke für deinen Vorschlag. Mit Threads habe ich bisher noch nie gearbeitet ;) Dein Code-Beispiel funktioniert aber genau so, wie ich es erwartet habe. Wie du schon gesagt hast, hat diese Implementierung den Nachteil, dass man neu mit der Maus ansetzen muss, sobald man die Minimalgröße in irgendeiner Weise beim Verkleinern unterschreitet.

Warum gibt es das CanResize-Event eigentlich nicht in Firemonkey? Wird dazu zwingend eine Funktionalität benötigt, die nur für Windows verfügbar ist?

Harry Stahl 5. Mai 2015 20:12

AW: Firemonkey From Constraints
 
Zitat:

Zitat von Scurra (Beitrag 1300126)
Warum gibt es das CanResize-Event eigentlich nicht in Firemonkey? Wird dazu zwingend eine Funktionalität benötigt, die nur für Windows verfügbar ist?

Ich würde mal sagen, das ist eines (von weiteren Dingen), die man noch nachrüsten kann und sollte. Ich habe mir mal die VCL-Lösung angesehen, das könnte man auch in FireMonkey implementieren, sollte dabei auch für den MAC gehen. Für die mobile Plattform hätte das nach erster Einschätzung wohl eher weniger Relevanz.

Wenn es eine Funktionalität sein sollte, die für Dich wichtig ist, bzw. oft benötigt wird, könntest Du ja mal einen Vorschlag zur Erweiterung bei Quality Central machen. Manche Dingen brauchen zwar länger (z.B. jetzt erst in XE8 die TImageList und Grafiken für die Buttons) und andere fehlen immer noch (Hints)), aber man soll ja die Hoffnung nicht aufgeben...

himitsu 5. Mai 2015 20:49

AW: Firemonkey From Constraints
 
Hints braucht man in Touchumgebungen doch nicht und da dort die meiste Arbeit rein geht, hat auf soeinen Pillepalle keiner Lust.
Und da dort (auf'm Handy) eh alles Vollbild ist, wozu braucht man da Constraints? :stupid:

Die FMX-TForm ist halt keine Form, sondern eine Komponente, welche auf den "Canvas" der jeweiligen Platform-Form draufgemalt wird.
Diese "Komponente" bekommt erst nach Änderung der Formgröße ihre neue Größe mitgeteilt und hier müsste Emba bei allen nötigen Platformen (Windows, MacOS ... Linux spart man sich ja) das Changing-Event ala OnCanResize ebenfalls im Parent implementieren und an die FMX-Form weitergeben.

Leider bietet TPlatformWin.HandleMessage keinen Event ala OnMessage an, wie in der VCL, sonst könnte man sich da ganz billig reinhängen. :wall:
Bei den Windows-Forms sollte man zwar an WM_WINDOWPOSCHANGING rankommen können, aber ich weiß auch nicht, wie man sich da bei der FMX-Form an die Messagebeandlung ranhängen kann.
Vielleicht hilft der TMessageManager, den ich im Code an paar Stellen sah? Oder jemand sucht mal nach der Parent-Form, welche FMX im Windows als Zeichenfläche benutzt.


Wenn jemand dort was macht, dann dauert das aber garantiert noch mindestens bis XE10. (also warten würde ich nicht drauf)

Harry Stahl 5. Mai 2015 22:16

AW: Firemonkey From Constraints
 
@himitsu:

Klar, auf mobilen Anwendungen braucht man keine Hints. Aber unter Windows und MAC ist es eine hilfreiche Sache.

Bei den Constraints sehe ich momentan nur EMBA, die das hier sauber im Framework implementieren könnten.

himitsu 5. Mai 2015 23:06

AW: Firemonkey Form Constraints
 
Pssst, das war natürlich ein Seitenhieb auf eine bestimmte Firma. :zwinker:

Drum haben auch schon mehrere versucht sich Hints selber zu basteln.
(Meine, aus dem FireMonkey 1 laufen leider so nicht mehr, da Emba mehrmals genügend im FMX umgebaut hat)


Und dann werd' ich jetzt mal 'nen Mod bitten die Überschrift zu reparieren.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:02 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz