Einzelnen Beitrag anzeigen

Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.537 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Firemonkey From Constraints

  Alt 1. Mai 2015, 16:58
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.

Geändert von Harry Stahl ( 1. Mai 2015 um 17:04 Uhr)
  Mit Zitat antworten Zitat