ClientWidth, TDirectoryEdit

Rund um die LCL und andere Komponenten
Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

ClientWidth, TDirectoryEdit

Beitrag von Sieben »

Beim Versuch, den Pfad in einem TDirectoryEdit zu ellipsifizieren, habe ich zunächst einmal dessen ClientWidth abgefragt. Es stellte sich aber heraus, dass die mit Width identisch ist, was für den Anwendungsprogrammierer, der wissen will, wieviel Platz er für die Darstellung der jeweiligen Werte hat, nicht hilfreich ist. Gut, frage ich also das enthaltene Edit. Da komme ich zwar leider nicht ohne weiteres ran, da protected, aber mit Crackerklasse geht's ja. Die Angabe war aber auch nicht wirklich hilfreich - obwohl ClientWidth nicht überschritten wurde, wurde der Text teilweise doch noch abgeschnitten. Zur Kontrolle dann mal ein ganz normales TEdit nach Width und ClientWidth befragt - identisch. One thing is for sure - Delphi kompatibel ist das gerade nicht.

Frage erstmal: war das auch schon in früheren Versionen so? Ich kann mir nicht vorstellen, dass das noch niemandem aufgefallen ist. Forumssuchen hier wie dort haben jedenfalls nichts einschlägiges ergeben.

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: ClientWidth, TDirectoryEdit

Beitrag von theo »

Nur mal so zum Verständnis.
Ein TEdit zu "ellipsifizieren" ist ja vielleicht nicht die beste Idee, da dieses doch die Eingabe 1:1 ermöglichen sollte.
Warum willst du überhaupt das TDirectoryEdit "überlisten"?
Nimm doch einfach einen TSelectDirectoryDialog und bastle dein eigenes Ding, mit einem TLabel z.B.
Oder verstehe ich da etwas falsch?

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: ClientWidth, TDirectoryEdit

Beitrag von Sieben »

Im TDirectoryEdit kannst du die direkte Eingabe ausschalten, eignet sich von daher also schon. Unschön ist in dem Zusammenhang dann allerdings, dass das Property Directory einfach auf Text geht, aber das ist eine andere Baustelle.

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: ClientWidth, TDirectoryEdit

Beitrag von theo »

Sieben hat geschrieben:
Di 25. Aug 2020, 15:22
Im TDirectoryEdit kannst du die direkte Eingabe ausschalten, eignet sich von daher also schon. Unschön ist in dem Zusammenhang dann allerdings, dass das Property Directory einfach auf Text geht, aber das ist eine andere Baustelle.
Ja gut, aber ein TEdit wo man nichts hinentippen kann, ist kein TEdit..
Eine reine Anzeigekomponente ist das TLabel, wie ich oben schon vorgeschlagen hatte.

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: ClientWidth, TDirectoryEdit

Beitrag von wp_xyz »

Sieben hat geschrieben:
Di 25. Aug 2020, 13:47
ellipsifizieren
Wow... Schon zum "Wort des Jahres" angemeldet?

Ich nehme an, du willst einen zu langen Text in einem Directory-Edit abschneiden und in der Mitte ein '...' einfügen, so dass der ganze Text in die Breite des Edit-Feldes passt.
Sieben hat geschrieben:
Di 25. Aug 2020, 13:47
Zur Kontrolle dann mal ein ganz normales TEdit nach Width und ClientWidth befragt - identisch. One thing is for sure - Delphi kompatibel ist das gerade nicht.
Wieso diese alternativen Fakten? Ein TEdit mit Width 80 hat in meinen eben durchgeführten Tests unter Lazarus Trunk, 1.8.4 und 1.0 eine ClientWidth von 76, genauso wie bei Delphi 10.3 Community Edition (Win 10).

Width ist die äußere Control-Breite (wichtig für den Parent), ClientWidth die innere (die für Clients zur Verfügung steht). Die zwei Pixel Unterschied links und rechts sind wahrscheinlich für den minimalen Rahmen. Ich denke, der Text ist für die Ausgabe noch um ein paar Pixel nach innen gerückt, so dass ControlWidth zu klein wird. Daher würde ich noch etwa 4 Pixel von ClientWidth abziehen:

Die folgende Routine funktioniert in meinen Tests mit einem TEdit, TDirectoryEdit und einem TFileNameEdit korrekt:

Code: Alles auswählen

procedure TForm1.AdjustText(AText: String);
var
  cnv: TControlCanvas;
  w: Integer;
begin
  cnv := TControlCanvas.Create;
  try
    cnv.Control := Edit1;

    w := Edit1.ClientWidth;
    Edit1.Text := MinimizeName(AText, cnv, w-4);

    w := TMyDirectoryedit(DirectoryEdit1).Edit.ClientWidth;
    DirectoryEdit1.Text := MinimizeName(AText, cnv, w-4);

    w := TMyfileNameEdit(FileNameEdit1).Edit.ClientWidth;
    FilenameEdit1.Text := MinimizeName(AText, cnv, w-4);
  finally
    cnv.Free;
  end;
end;  

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: ClientWidth, TDirectoryEdit

Beitrag von Sieben »

Vielen Dank für die implizite Beantwortung meiner Frage - war also in früheren Versionen anscheinend nicht so. Bei mir - Gerätschaften siehe Profil - bei beiden Eigenschaften der Wert 80.

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: ClientWidth, TDirectoryEdit

Beitrag von wp_xyz »

Das liegt nicht an der Lazarus-Version sondern an Ubuntu. Offenbar meldet dein WidgetSet an die LCL, dass bei TEdit Width und ClientWidth gleich sein sollen. Bei Windows ist das anders. Das ist die Folge der Grundidee hinter der LCL, nämlich so viel wie möglich vom Widgetset erledigen zu lassen, so dass die Anwendung letztendlich zu den anderen Programmen auf diesem Betriebssystem passt. Bei allen Details, die vom Widgetset abhängen, sind solche Inkompatibilitäten möglich. Ein häufige Frage ist z.B.: "Warum kann ich die Button-Farbe nicht ändern?" - genau aus diesem Grund.

Außerhalb von Windows sollte man auch nicht von Delphi-Kompatibilität sprechen, denn Delphi's VCL, die von Lazarus in der LCL nachgebildet wird, gibt es nur unter Windows.
Zuletzt geändert von wp_xyz am Di 25. Aug 2020, 17:28, insgesamt 1-mal geändert.

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: ClientWidth, TDirectoryEdit

Beitrag von Sieben »

Danke, mit der Erklärung kann ich etwas anfangen. Wenn man allerdings davon ausgeht, dass - ich nenne es dann mal Ideen-kompatibel - die Client* Properties eben den Bereich angeben sollten, der für die tatsächliche Anzeige des Wertes zur Verfügung steht, eben abzüglich des Rahmens etc, dann ist das wie gesagt keine hilfreiche Angabe.

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: ClientWidth, TDirectoryEdit

Beitrag von wp_xyz »

Der Rahmen ist nur die Hälfte des Problems. Offenbar wird der Text beim TEdit innerhalb des ClientRect nicht direkt in der Ecke gezeichnet, sondern wird um ein paar Pixel nach innen gerückt. Leider sieht man das nicht im Code, da die Ausgabe vom Widgetset gemacht wird. Aber ich stelle mir vor, dass das ähnlich ist wie beim TStringGrid wo der Text nicht extakt im übergebenen Rechteck steht, sondern in dem um "varCellPadding" allseits geschrumpften (InflateRect(ARect, -varcellPadding, -varCellPadding)). Natürlich ist dieser Versatz ebenfalls eine Sache des Widgetset, und es gibt eine gewisse Wahrscheinlichkeit, dass das was du unter Linux für den Versatz annimmst bei Windows nicht mehr stimmt und bei macOS auch wieder nicht. Korrekterweise müsstest du die entsprechende Funktion des Widgetset aufrufen, um den Versatz oder das tatsächlich für die Ausgabe verfügbare Rechteck zu ermitteln (frage mich nicht, wie das geht...).

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: ClientWidth, TDirectoryEdit

Beitrag von Sieben »

Genau das würde ich ja von den Client*-Properties erwarten... dass man eben keine Annahmen machen muss, sondern darauf bauen kann, dass jeweils genau der 'beschreibbare' Bereich zurückgegeben wird. Erst dann wäre es eben auch egal, ob ClientWidth bei einem 80er TEdit bei einem Widgetset 76 zurückgibt und bei einem anderen meinetwegen nur 74. Und ich bin auch immer noch geneigt, es als Bug anzusehen, dass ClientWidth einfach den gleichen Wert zurück gibt wie Width. Das kann nun wirklich nicht der Sinn sein.

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

Re: ClientWidth, TDirectoryEdit

Beitrag von Winni »

Hi!

Also es gibt zwei Möglichkeiten:
Entweder Du freundest Dich mit dem Konzept von Lazarus an:
Wir benutzen das vorhandene Look & Feel des vorhandenen OS bzw. Widget Sets an und passen so mit unserer App in die Umgebung.

Oder Du schnitzt Dir Deine Komponenten selbst .

Dass Win7, Win10, gtk, qt, Mac und andere jeweils verschiedene Vorstellungen von ihrem Widget Set haben, ist schon deshalb klar, weil sie möglichst auf einen Blick erkannt werden möchten.

Und manche Informationen geben bestimmte Umgebungen einfach nicht zurück. gtk hat ewig das ClientRect einer Form unter Linux um Geheimnis gemacht. Und so war das ClientRect identisch mit den Dimensionen der Form. Und ohne Klimmzüge kommt man heute noch nicht an die Höhe des Titlebars unter gtk ran.

Also gewöhne Dich an die Situation.

Oder bau Dir sieben Komponenten selbst.

Winni

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: ClientWidth, TDirectoryEdit

Beitrag von Sieben »

Danke. Sorry, war nicht mein Tag gestern.

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: ClientWidth, TDirectoryEdit

Beitrag von Sieben »

Dazu noch mal eine Verständnisfrage. Ich beschäftige mich gerade ein wenig mit den Sourcen von TTreeView und TShellTreeView, wobei die Implementation von ersterem ja in einer .inc-Datei, die von letzterem jedoch in der gleichen .pas, in der auch das interface deklariert ist. Verstehe ich das soweit richtig, dass treeview.inc widgetset-spezifisch ist, während die Unit ShellCtrls sozusagen weit genug 'oben' sitzt, um das Spezifische den 'Unterklassen' zu überlassen?

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: ClientWidth, TDirectoryEdit

Beitrag von wp_xyz »

comctrls.pp ist eine Riesendatei mit viele Komponenten. Um nicht die Übersicht zu verlieren, hat man die Implementierung der einzelnen Komponenten in include-Dateien ausgelagert -- das hat nichts mit Widgetset zu tun.

Der widgetset-spezifische Code liegt für jede Unit in den jeweiligen Ordnern lcl/interface/<widgetset>; die units heißen wie die Haupunits, aber mit der Vorsilbe "<widgetset>ws"; für "comctrls.pp" und Win32 wäre das "win32wscomctrls.pp". In dieser Datei findest du für TTreeView die passende Interface-Klasse als TWin32WSTreeView. Die Methoden dieser Klasse werden irgendwann von der Hauptklasse aufgerufen; auf diese Weise wird der für das Widgetset passende Code verwendet.

Der Schlüssel, ob eine Komponente widgetset-spezifischen Code verwendet, ist die Methode WSRegisterClass. Bei (Custom)ShellTreeView gibt es diese Methode nicht, das heißt, dass alle widgset-spezifischen Sachen bereits im Vorfahren abgehandelt werden.

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: ClientWidth, TDirectoryEdit

Beitrag von Sieben »

Also nicht völlig, nur ziemlich daneben. Danke.

Antworten