Bilder in Stringridzellen

Antworten
Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Bilder in Stringridzellen

Beitrag von Aloxen »

Hey hey, mal wieder eine Frage
Ich möchte in einem Stringrid in jede Zelle ein Bildeinfügen. Das Bild ist nicht in jeder Zelle gleich
Ich habe bisher im Internet das gefunden bzw selber geschrieben:

Code: Alles auswählen

procedure TForm4.FormActivate(Sender: TObject);
var
  bmp:TGraphic;
  theRect: TRect;
  OriginePoint:TPoint;
begin
  DrawGrid1.Width:=400;
  DrawGrid1.height:=200;
  bmp := Tbitmap.Create;
  OriginePoint.Create(0,0);
  theRect.Create(OriginePoint,10,10);
  bmp.LoadFromFile('Blocks\Holz1\Holz1.bmp');
  SetCellPicture(theRect,bmp,StringGrid1);
end;

procedure TForm4.SetCellPicture(Rect: TRect; Picture: TGraphic; Grid : TStringGrid);
begin
  Grid.Canvas.StretchDraw(Rect, Picture);
end; 
Ich habe keine Ahnung was genau ich da mache. Es fehlt auch eine Zellenangabe. Ich habe auch oft die OnDrawCell bei einem Drawgrid gefunden, aber auch da hatte ich keinen Erfolg.
Ich brauche theoretisch auch nicht zwingend ein Stringgrid, ich brauche nur ein Grid wo ich verfolgen kann, auf welches Bild der Nutzer geklickt hat.

Kennt sich da jemand aus?

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

Re: Bilder in Stringridzellen

Beitrag von theo »

Kann man im OnDrawCell Event machen.
Wenn die Bilder in einer ImageList sind, geht das z.B. so:

Code: Alles auswählen

procedure TForm1.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
  aRect: TRect; aState: TGridDrawState);
begin
  if (ACol=0) and (ARow<ImageList1.Count-1) then
    ImageList1.Draw(TStringGrid(Sender).Canvas,ARect.Left,ARect.Top,ARow);
end;    
Hier wird nur die erste Spalte (ACol=0) bestückt.

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

Re: Bilder in Stringridzellen

Beitrag von wp_xyz »

Es gibt im Ordner examples/gridexamples/embedded_images ein Beispielprojekt, wie man das StringGrid für Bilder erweitern könnte. Ist allerdings wahrscheinlich etwas zu komplex für deine Anforderung (denn du willst die Bilder nicht mit der Maus veschieben können).

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Bilder in Stringridzellen

Beitrag von Aloxen »

theo hat geschrieben:
Sa 19. Nov 2022, 13:14
Kann man im OnDrawCell Event machen.
Was genau ist denn dieses OnDrawCell Event? Wodurch wird es ausgelöst bzw wodurch löse ich es aus?

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

Re: Bilder in Stringridzellen

Beitrag von theo »

Aloxen hat geschrieben:
So 20. Nov 2022, 01:06
Was genau ist denn dieses OnDrawCell Event? Wodurch wird es ausgelöst bzw wodurch löse ich es aus?
Im Objektinspektor oben die Komponente auswählen (oder auf dem Formular), dann unten im "Ereignisse" Tab bei OnDrawCell ins weisse Feld doppelklicken. Dann hast du das Gerüst für die Ereignisbehandlungsmethode im Code.

objinsp.png
objinsp.png (40.89 KiB) 1297 mal betrachtet

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Bilder in Stringridzellen

Beitrag von Aloxen »

Ja, gefunden habe ich die schon aber wie kann ich die Funktion auslösen oder wodurch wird sie ausgelöst? heißt onDrawCell dass sie beim Erstellen des Grids bei jedem mal wenn eine Zelle gezeichnet wird ausgeführt wird, oder nur wenn ein Nutzer draufklickt oder muss ich sie sogar manuell aktivieren?

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

Re: Bilder in Stringridzellen

Beitrag von theo »

Das Event "onDrawCell" wird für jede Zelle aufgerufen, die neu gezeichnet muss.
Welche Zelle das gerade ist, kannst du den Parametern aCol und aRow entnehmen.
Probier's doch einfach aus!

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Bilder in Stringridzellen

Beitrag von Aloxen »

Okay ich habe ein bisschen was ausprobiert mit dem OnDrawCell Event:

Code: Alles auswählen

procedure TForm4.FormActivate(Sender: TObject);
begin
  k:=1;
end;

procedure TForm4.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
  aRect: TRect; aState: TGridDrawState);
begin
  if k > (StringGrid1.ColCount*StringGrid1.RowCount) then k:=1;
  ImageList1.Draw(TStringGrid(Sender).Canvas,ARect.Left,ARect.Top,k);
  inc(k);
end;  
Es macht auf den ersten Blick genau das was ich möchte, aber wenn man dann auf das StringGrid klickt und eine Zelle auswählt, verschieben sich die Bilder. Offensichtlich stimmt die k Variable nicht. Was kann ich dagegen tun und ist es ein logischer Fehler oder sollte ich lieber eine andere Funkton nehmen?

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

Re: Bilder in Stringridzellen

Beitrag von theo »

Ich verstehe dein Problem, aber so würde ich das nicht lösen.

Wie viele Bilder hast du denn? Wie viele pro Reihe?

Ich würden den Bildindex in jedem Fall aus aCol und aRow berechnen.

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Bilder in Stringridzellen

Beitrag von Aloxen »

Es soll eigentlich eine unbekannte Anzahl von Bildern möglich sein. Zunächst reicht es, dass ich weiß dass es nicht mehr Bilder als es Stringlistzellen gibt. Das StringGrid soll einfach alle Bilder aus der Imagelist Reihe für Reihe anzeigen. Im Moment habe ich 8 Bilder, d.h. bei einem Stringgrid von 4*4 Zellen bleibt ne Menge leer. Diese werden auch als Leer angezeigt. Wenn ich dann aber auf das Stringrid klicke, werden die Bilder neu angeordnet, in anderen Zellen weiter unten. Bei jedem Klick verändert sich die Anordnung erneut. Das OnDrawCell Event wird also jedes mal, wenn man auf eine Zelle klickt und diese kleine Rote Umrandung um die angeklickte Zelle erscheint, erneut ausgeführt. Beim erneuten ausführen muss irgendwas nicht mehr so hinhauen wie beim erstellen des Stringgrids.

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

Re: Bilder in Stringridzellen

Beitrag von theo »

Wie gesagt, nimm ACol und ARow als Basis für die Berechnung des Index.
Und noch ein Tipp: In der Computerei fängt (fast) alles mit 0 an, die Imagelist auf jeden Fall.
Also k:=1 ist wahrscheinlich schon mal falsch. :wink:

Code: Alles auswählen

procedure TForm1.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
  aRect: TRect; aState: TGridDrawState);
const MaxCol=5;
begin
  TStringGrid(Sender).Canvas.TextOut(aRect.Left,ARect.Top,(aCol+MaxCol*aRow).ToString);
end;  

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

Re: Bilder in Stringridzellen

Beitrag von wp_xyz »

Ein StringGrid speichert seine Zell-Texte (Cells[col, row]) nicht direkt, sondern in einem Record CellProps:

Code: Alles auswählen

type
  PCellProps= ^TCellProps;
  TCellProps=record
    Attr: pointer;
    Data: TObject;
    Text: pchar;
  end;
Das Feld Text ist als Cells zugänglich, und für Data gibt es eine Property Objects[col, row]. Attr ist gedacht für spezielle Zellformatierung, wie Schriftarten, zusammenhängende Zellen etc. - nur hat das noch niemand implementiert, und es ist auch noch nicht nach außen geführt.

Am einfachsten kriegst du die Bilder als ImageIndex ins Grid, indem du die Eigenschaft Objects[] durch einen Type-cast nach Integer als ImageIndex zweckentfremdest:

Code: Alles auswählen

      StringGrid1.Cells[c, r] := <irgendein Text>;
      StringGrid1.Objects[c, r] := TObject(PtrUInt(12));  // Das Bild mit dem Index 12 in dieser Zelle verwenden
....      
procedure TForm1.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
  aRect: TRect; aState: TGridDrawState);
var
  imgIndex: Integer;
begin
    imgIndex := PtrUInt(StringGrid1.Objects[ACol, ARow]);
    ImageList1.Draw(StringGrid1.Canvas, ARect.Left+varCellPadding, ARect.Top, imgIndex);
    ...
Siehe beigefügtes Projektchen, in dem jeder Zelle ein zufälliger ImageIndex zugewiesen wird.
Dateianhänge
imagelist.zip
(9.22 KiB) 49-mal heruntergeladen

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Bilder in Stringridzellen

Beitrag von Aloxen »

@theo
Hey Danke das funktioniert. Ja ich weiß dass man bei Null anfängt aber ich habe mich hier nach den TextureIDs der Bilder gerichtet und die ID 0 ist für eine Textur vergeben, die nicht in dieser Liste sein soll. Deshalb soll die 0 nicht gezeichnet werden.

Weißt du zufälligerweise noch wie ich die Bilder auf die volle Breite der Zelle bekomme? Sie sind bei mir jetzt sehr klein.

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

Re: Bilder in Stringridzellen

Beitrag von theo »

Aloxen hat geschrieben:
So 20. Nov 2022, 19:22
Weißt du zufälligerweise noch wie ich die Bilder auf die volle Breite der Zelle bekomme? Sie sind bei mir jetzt sehr klein.
Mit StretchDraw:

Code: Alles auswählen

procedure TForm1.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
  aRect: TRect; aState: TGridDrawState);
const MaxCol=4;
begin
    ImageList1.StretchDraw(TStringGrid(Sender).Canvas,aCol+MaxCol*aRow,ARect);
end;    
Aber die Qualität wird beim vergrössern natürlich schlechter, deshalb besser grössere Bilder in die ImageList legen.

Antworten