TMultiButton, ein Button mit einem integrierten Button

Zur Vorstellung von Komponenten und Units für Lazarus
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: TMultiButton, ein Button mit einem integrierten Button

Beitrag von Winni »

Nimral hat geschrieben:
Fr 21. Mai 2021, 10:05

.... wobei dort ein "Windows-Manifest" vom Himmel fällt, wo ich mich also auch noch irgendwie reinfuchsen muss.

Armin.
Hi

Niemand zwingt Dich, ein Windows-Manifest zu benutzen.
Das kann man auf der allerersten Seite der Projekt-Einstellungen ausschalten.

Das hat außerdem den Vorteil, dass nieman mehr Deine schöne App mit hässlichen Themes verunstalten kann.

Winni

Nimral
Beiträge: 390
Registriert: Mi 10. Jun 2015, 11:33

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von Nimral »

(Unnützes Posting gelöscht)

Nimral
Beiträge: 390
Registriert: Mi 10. Jun 2015, 11:33

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von Nimral »

Guten Abend, oder besser, guten Morgen, Bernd!

Ich glaube wir können die Korken knallen lassen, ich habe jetzt eine Weile mit den Features gespielt die mir wichtig sind, also auch Drag'n'Drop, und Dein Button hat sich keinen Patzer erlaubt, er scheint perfekt zu funktionieren. Auch das Skalieren des Images klappt, jedenfalls mit der von WP vorgeschlagenen Methode, das größte Image, bei mir 36x36, zu hinterlegen. Es schaut runterskaliert immer noch ordentlich aus. Auch das mir High-DPI funktioniert, jetzt wo ich verstanden habe worauf ich achten muss. Ich wollte dann noch testweise kleinere Images hinterlegen, aber das mit der ImageList habe ich noch nicht im Griff. Da belästige ich aber wp nochmal im anderen Thread.

Gratuliere, und herzlichen Dank, dass Du Dir die Mühe machst!

HG, Armin.

Nimral
Beiträge: 390
Registriert: Mi 10. Jun 2015, 11:33

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von Nimral »

Hi Bernd,

eine kleine Unschönheit: wenn ein Button den Fokus wieder hergeben muss (nach hover) wird offenbar ein gesetzter Radius nicht berücksichtigt, und es erscheinen kleine farbige Eckchen, die permanent stehen bleiben.
2021-05-26 14_29_51-Lazarus-IDE v2.0.12 r64642 - HoverProblem (Debuggen...).png
2021-05-26 14_29_51-Lazarus-IDE v2.0.12 r64642 - HoverProblem (Debuggen...).png (5.8 KiB) 3816 mal betrachtet
Einfach mit der Maus über den Button fahren reicht, man muss nicht klicken. MB1 hat das Problem nicht, weil ich FocusedOn ausgeknipst habe.

Außerdem: gab es einen Grund, die Anchors nicht zuzulassen?

HG, Armin.
Dateianhänge
MultiButtonBugReports.zip
(131.97 KiB) 107-mal heruntergeladen

wennerer
Beiträge: 518
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hi Armin,
ja da hat sich was eingeschlichen durch die Umstellerei von mir. Jetzt sollte es gehen. Habe die Anchors vererbt, hatte keinen Grund (ich werde nur nicht so richtig warm damit :D ).
In der Testversion 7.6 habe ich jetzt auch wie von wp_xyz beschrieben die Skalierung des Images installiert (hoffe ich zumindest). Bei mir zeigt es jetzt unter Win10 die verschiedenen Größen bei Bildschirmskalierung an. Ich hab da in deine Form noch einen Button mit skalierten Images reingezogen. Kannst ja mal testen ob die bei dir auch richtig angezeigt werden (die haben verschiedene Farben) wenn du mal auf 125% oder 150% usw. umstellst.

Viele Grüße
Bernd
Dateianhänge
Testversion7.6.zip
(87.75 KiB) 106-mal heruntergeladen

wennerer
Beiträge: 518
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hallo ins Forum,
dank dem Interesse von Nimral an meinem MultiButton ist innerhalb sehr kurzer Zeit einiges an Änderungen eingeflossen. Da es mir auf die Schnelle nicht immer möglich war sorgfältig zu testen habe ich mir nun nochmal etwas Zeit genommen um den MultiButton noch einigen Tests zu unterziehen. Ich habe wie erwartet noch ein paar Fehler korrigiert. Sollte jemand Lust und Zeit haben und den MultiButton ebenfalls testen, freue ich mich über Rückmeldungen (besonders wenn was nicht geht).
Falls wp_xyz zufällig mit liest möchte ich mich nochmal für die Erklärungen und die Code Beispiele bezüglich Bildschirmskalierung und Imagelist recht herzlich bedanken. Das hätte ich sonst nicht hinbekommen. Ich habe es eventuell nicht 100% richtig umgesetzt aber bei mir scheint es unter Win10 zu funktionieren.
Die neueste Version 8 (und ein paar Testprojekte) stelle ich in den ersten Beitrag.

Viele Grüße
Bernd

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

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wp_xyz »

Beim Drüberfliegen ist mir nicht großes aufgefallen, bis auf

- TImageIndexPropertyEditor.ListDrawValue zeichnet die Bilder mit absoluten Koordinaten und mit der auflösungsunabhängigen Draw-Methode der ImageList. Ich könnte mir vorstellen, dass die Bilder dann im Objekt-Inspektor in der IDE nicht richtig skalieren.

- Und bei TMultiButton.DrawTheButton und noch bei ein paar anderen Methoden verwendest du ein Hilfs-TImage. Muss das sein, in der Draw-Methode so ein schweres Control zu verwenden?

wennerer
Beiträge: 518
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hallo,
vielen Dank für die Antwort!

wp_xyz schrieb:
Und bei TMultiButton.DrawTheButton und noch bei ein paar anderen Methoden verwendest du ein Hilfs-TImage. Muss das sein, in der Draw-Methode so ein schweres Control zu verwenden?
Naja hat halt funktioniert, aber wenn du es schon so formulierst dann gehe ich mal davon aus ich sollte es lieber nicht so machen. Grund ist wohl das die Images bei jedem Neuzeichnen erzeugt und freigegeben werden was wohl auf die Leistung geht? Jedenfalls habe ich die Hilfsimages rausgeschmissen und dafür Bitmaps genommen. Ich hoffe das dies besser ist.

wp_xyz schrieb:
TImageIndexPropertyEditor.ListDrawValue zeichnet die Bilder mit absoluten Koordinaten und mit der auflösungsunabhängigen Draw-Methode der ImageList. Ich könnte mir vorstellen, dass die Bilder dann im Objekt-Inspektor in der IDE nicht richtig skalieren.
Also da hab ich jetzt ziemlich viel herum probiert und konnte keinen Unterschied zu einer normalen ImageList feststellen. Meine Beobachtungen waren folgende:
Alles was in TImageIndexPropertyEditor gesetzt wird wirkt sich nur im OI aus, also hier:
imOi.png
imOi.png (9.91 KiB) 3751 mal betrachtet
Unter Linux wird Left anders gesetzt wie unter Windows, das habe ich etwas angepasst. Ich konnte auch Strechdraw verwenden dann skaliert es das Bild in die komplette Zeile. Es ist aber egal wie groß das Bild ist es wird mit Draw hier immer korrekt angezeigt.

Alles was im BildlistenEditor angezeigt wird passiert irgenwo hier: TImageListEditorDlgProperty. Ich befürchte aber um hier die Vorschau zu ändern müsste man direkt in dem Editor was ändern. Wie schon gesagt verhält sich da die ImageList im MultiButton identisch mit einer "normalen ImageList". Wenn ich alles genauso mache wie du es in dem Beitrag viewtopic.php?f=18&t=13690&start=15 beschreibst dann geht auch alles so wie es soll (denke ich zumindest). Wird das Bild zu Groß wird es dann auf der linken Seite nicht mehr komplett dargestellt (wird also denke ich nichts skaliert). Rechts wird halt nur die vorgewählte Größe angezeigt.
Bildlisteneditor.png
Bildlisteneditor.png (42.28 KiB) 3751 mal betrachtet
Die neueste Version 8.1 stelle ich wieder in den ersten Beitrag.

Viele Grüße
Bernd

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

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wp_xyz »

wennerer hat geschrieben:
So 30. Mai 2021, 09:17
Also da hab ich jetzt ziemlich viel herum probiert und konnte keinen Unterschied zu einer normalen ImageList feststellen.
Ich habe mir jetzt mal den TMultiButton auf Win10 (96ppi) und Win7 (144ppi) installiert und sehe genau das Problem, das ich erwartet habe (vielleicht nicht gut genug beschrieben): Das Bitmap ist in der Combobox des Objektinspektors in beiden Fällen gleich groß, entsprechend seiner 96ppi-Größe, es wird nicht skaliert.

Warum überhaupt integrierst du die ImageList in den Button? Normalerweise ist die ImageList eine externe Komponente, die nur beim TBitBtn, TSpeedButton, TToolbar usw "eingehängt", aber dort nicht selbst verwaltet wird. Dein Ansatz macht es erforderlich, dass für jeden MultiButton, der mit demselben Bild schon irgendwo mal verwendet worden ist, die Bilder neu einzulesen. Vom verschwendeten Speicherplatz mal abgesehen, ist für mich das Ausfüllen einer ImageList eine sehr lästige Aufgabe, vor allem wenn die verschiedenen Bildgrößen nicht griffbereit im selben Verzeichnis liegen. Bei der üblichen Herangehensweise holt man sich an zentraler Stelle eine ImageList (z.B. in einem DataModule), füllt sie mit allen benötigten Bildern, und jede Komponente, die ein Bild braucht, bedient sich daraus. Das ist bei deinem Konzept nicht möglich.

P.S.
Warum, übrigens, ist in den Screenshots ein helles Quadrat bei ImageIndex=-1? Hast du etwa ein leeres Platzhalter-Bitmap? Das erscheint mir unnötig, denn du kannst beim Zeichnen das Bild überspringen, wenn der ImageIndex -1 ist. Und überhaupt: Wenn du die ImageIndex-Property von TImageIndex ableitest, stellt die IDE schon den passenden Propertyeditor zur Verfügung, und du musst dich darum gar nicht mehr kümmern.
Dateianhänge
TMultiButton_ImageIndex_96ppi.png
TMultiButton_ImageIndex_96ppi.png (10.62 KiB) 3739 mal betrachtet
TMultiButton_ImageIndex_144ppi.png
TMultiButton_ImageIndex_144ppi.png (43.13 KiB) 3739 mal betrachtet

wennerer
Beiträge: 518
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hallo wp_xyz,
zunächst vielen Dank das du dir die Mühe gemacht hast den MultiButton zu installieren.
Ich habe es eben nochmal unter Win10 getestet und bei mir sieht es (wieso auch immer) so aus:
Ansicht100_150.png
Ansicht100_150.png (36.73 KiB) 3729 mal betrachtet
Viel interessanter für mich ist aber der Rest deiner Antwort. Du hast mir da jede Menge Sachen zum Nachdenken gegeben (Campions league trifft auf Amateuerklasse :D ).
Obwohl es (für meine Möglichkeiten) ganz passabel funktioniert habe ich da bestimmt noch viele Verwirrungen drin. Und das mit der Imagelist gehört wohl dazu. Ich muss jetzt mal kräftig nachdenken wie ich das am besten angehe. Über so was wie Speicherverbrauch habe ich noch gar nicht wirklich richtig nachgedacht. Eventuell sollte ich den mal Messen und mit anderen Controlls vergleichen. Die Sachen welche du unter PS aufführst muss ich natürlich auch angehen!

Viele Grüße
Bernd

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

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wp_xyz »

wennerer hat geschrieben:
So 30. Mai 2021, 18:12
Ich muss jetzt mal kräftig nachdenken wie ich das am besten angehe.
Ich glaube, das geht relativ einfach:
- TMultiButton.Create darf die Imagelist nicht erzeugen (kommentiere FMessageButton.FImageList := TImageList.Create und FImageList := TImageList.Create aus)
- Das Zerstören der selbsterzeugten ImageListen darf auch nicht sein, aber weil du als Owner "self" angegeben hast, musst du dich darum nicht kümmern.
- TMultibutton.SetImageList darf nicht die Bilder kopieren, sondern muss einfach die als AValue angegebene an die interne Variable (FImagelist) zuweisen. Die Imagelisten sind ja wie alle Objekte Pointer, d.h. wenn TMultiButton eine externe ImageList als Variable verwendet, dann hat sie Zugriff auf die dort gespeicherten Bilder, ohne diese kopieren zu müssen.
- Die Property-Editor für ImageList und ImageIndex sind nicht mehr nötig. ImageIndex solltest du aber als TImageIndex deklarieren (statt als Integer), denn dann wird automatisch der vorhandene ImageList-PropertyEditor verwendet.
- Die intern verwendete ImageList würde ich als TCustomImageList deklarieren, statt als TImageList. Das hätte den Vorteil, dass du, wenn jemand einmal z.B. eine TSvgImageList von TCustomImageList ableiten würde, du diese direkt verwenden könntest.
wennerer hat geschrieben:
So 30. Mai 2021, 18:12
Über so was wie Speicherverbrauch habe ich noch gar nicht wirklich richtig nachgedacht. Eventuell sollte ich den mal Messen und mit anderen Controlls vergleichen.
Naja, das ist unschön, aber eher nebensächlich. Wichtiger ist, dass man die Bilder in jeden Button neu eintragen muss.

Nimm dir einfach einmal ein Control der LCL, das eine ImageList verwendet, als "Spick"-Quelle. Leider ist das wegen der Widgetset-Infrastruktur nicht immer klar zu erkennen. Probier's mal mit TCustomGrid und seiner FTitleImageList.

wennerer
Beiträge: 518
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hallo,
ich hoffe das mir jemand nochmal weiterhelfen kann. Ich probiere wie von wp_xyz vorgeschlagen eine ImageList mit dem MultiButton zu verbinden.
wp_xyz schrieb:
ImageIndex solltest du aber als TImageIndex deklarieren (statt als Integer), denn dann wird automatisch der vorhandene ImageList-PropertyEditor verwendet.
Leider fehlt mir an der Stelle noch irgend ein Baustein den ich nicht finden kann. Bei mir wird im OI unter ImageIndex nur -1 angezeigt obwohl in der ImageList die auf der Form liegt und bei Images ausgewählt ist eine Png geladen ist. Gebe ich im OI bei ImageIndex einfach mal eine 0 ein wird die Png gezeichnet.
Ich kann mich jetzt auch daran erinnern das ich damit schonmal herumgetestet habe und mangels besserer Lösung dann den PropertyEditor überschrieben habe. Ich habe folgenden minimal Code getestet und komme da leider nicht weiter.

Code: Alles auswählen

unit TestImage;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ImgList,
  ExtCtrls;

type

  { TTestImage }

  TTestImage = class(TCustomControl)
  private
    FImageIndex: TImageIndex;
    FImageList: TImageList;
    procedure SetImageIndex(AValue: TImageIndex);
    procedure SetImageList(AValue: TImageList);

  protected

  public
   constructor Create(AOwner: TComponent); override;
   destructor  Destroy; override;
   procedure   Paint; override;
  published
   property ImageIndex : TImageIndex read FImageIndex write SetImageIndex default -1;
   property Images  : TImageList read FImageList write SetImageList;

  end;

procedure Register;

implementation

procedure Register;
begin
  {$I testimage_icon.lrs}
  RegisterComponents('Standard',[TTestImage]);

end;

{ TTestImage }

procedure TTestImage.SetImageIndex(AValue: TImageIndex);
begin
  if FImageIndex=AValue then Exit;
  FImageIndex:=AValue;
end;

procedure TTestImage.SetImageList(AValue: TImageList);
begin
  if FImageList=AValue then Exit;
  FImageList:=AValue;

end;

constructor TTestImage.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

end;

destructor TTestImage.Destroy;
begin
  inherited Destroy;
end;

procedure TTestImage.Paint;
var aImage : TImage;
begin
  inherited Paint;
  canvas.Brush.Color:=clWhite;
  canvas.FillRect(0,0,width,height);
  aImage := TImage.Create(nil);
  Images.DrawForControl(canvas,2,2,FImageIndex,16,aImage,true);
  aImage.Free;
end;

end.
Viele Grüße
Bernd
Dateianhänge
ImageListTest.zip
(67.67 KiB) 106-mal heruntergeladen

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

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wp_xyz »

Der Code funktioniert, bis auf die Kleinigkeit, dass die Komponente nach der Änderung des ImageIndex (und der ImageList) nicht neu gezeichnet wird (--> Invalidate).

Ich habe auch die Paint-Routine so umgebaut, dass die ImageList direkt auf den Canvas der Komponente zeichnet, nicht erst über ein TImage-Hilfsobjekt.
Dateianhänge
ImageListTest-wp.zip
(7.69 KiB) 112-mal heruntergeladen

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1435
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von fliegermichl »

Der Vollständigkeit halber sollte in Paint geprüft werden, ob fImageList <> nil ist weil es sonst kracht.

wennerer
Beiträge: 518
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hallo,
@fliegermichl: ich werde es so verwenden, Danke.

@wp_xyz: ich habe es nun unter Linux und Windows10 in Stable und Trunk getestet. Bei mir geht es aber immer noch nicht. Ich denke deshalb das ich mich nicht verständlich genug ausgedrückt habe und deshalb ein Missverständnis vorliegt. In der Form wird es schon richtig gezeichnet aber im ObjektInspektor kann ich nur -1 auswählen bzw. sind dort auch keine Vorschau Bilder zum Auswählen. Irgendwas fehlt bei mir da wohl noch damit hier was angezeigt wird:
ImageIndex.png
ImageIndex.png (60.26 KiB) 3655 mal betrachtet
Viele Grüße
Bernd

Antworten