Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - ImageList - schnelle Anzeige
hRb - Mo 04.12.17 16:06
Titel: ImageList - schnelle Anzeige
Hallo Freunde,
ich möchte an Vorgängerfragen zur ImageList anknüpfen. Habe schon seit längerem in kleines Programm zur Datei-Anzeige und zum -Umbenennen; dargestellt in einem StringGrid. Dabei ist auch Verschieben nach oben/unten realisiert. Gerne hätte ich das Verschieben(Sortieren) auch optisch realisiert und will ein ImageList-Objekt zur Realisierung hinzufügen.
In einem Lehrbuch fand ich zu einem "Diabetrachter" folgende Befehlsfolge (über einem Image1-Objekt liegt ein Memo, das wechselseitig visible wird):
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| procedure TForm1.FileListBox1Click(Sender: TObject); var FileExt: string[4]; begin FileExt := UpperCase(ExtractFileExt(FileListBox1.Filename)); if (FileExt='.BMP')or(FileExt='.ICO')or(FileExt='.WMF')or(FileExt='.JPG') then begin memo1.visible := false; try Image1.Picture.LoadFromFile(FileListBox1.Filename); if FileExt = '.JPG' then Image1.Picture.Graphic := Image2.Picture.Graphic else if FileExt = '.BMP' then Image1.Picture := Image1.Picture else if FileExt = '.ICO' then Icon := Image1.Picture.Icon else if FileExt = '.WMF' then Image1.Picture.Metafile := Image1.Picture.Metafile; except messagebox(0,'Grafik fehlerhaft','Problem',16); end; end; if (FileExt='.TXT')or(FileExt='.PAS')or(FileExt='.INI')or(FileExt='.BAT')or(FileExt='.CMD')or(FileExt='.BAS') then begin memo1.visible := True; try memo1.lines.clear; memo1.lines.LoadFromFile(FileListBox1.Filename); except messagebox(0,'Datei fehlerhaft','Problem',16); end; end; end; |
Ich habe dieses Beispiel verändert und zeige in drei Image-Objekten die aktive Datei, sowie noch Vorgänger und Nachfolger an. Es funktioniert, aber..
- das Verfahren ist viel zu langsam (jeweils LoadFromFile)
- beim Image-Objekt muss der Bildtyp (bmp, ico, jpg, etc) eingestellt werden, sonst ggf Laufzeitfehler. Da es x-Grafikformate gibt, müsste die ggf. alle abgefragt werden
Etwas neidisch schaue ich da auf die Geschwindigkeit beim Explorer, der alle Dateien anzeigt.
Muss ich statt Image- ein ImageList-Objekt verwenden und wenn ja:
Frage: Gibt es im Forum ein Codebeispiel wie man eine ImageList mit den Dateien eines Verzeichnisses füllt? - in Mimiaturansicht/Gr0ße Symbole?
oder kann man auf die tumb.db des Verzeichnisses zugreifen (wie)?
Narses - Mo 04.12.17 17:15
Moin!
hRb hat folgendes geschrieben : |
Etwas neidisch schaue ich da auf die Geschwindigkeit beim Explorer, der alle Dateien anzeigt.
Muss ich statt Image- ein ImageList-Objekt verwenden und wenn ja:
Frage: Gibt es im Forum ein Codebeispiel wie man eine ImageList mit den Dateien eines Verzeichnisses füllt? - in Mimiaturansicht/Gr0ße Symbole? |
Bei der ImageList bin ich mir sicher, dass sie nicht für diesen Zweck „erfunden“ wurde, das darunter liegende native Windows-Objekt ist nämlich relativ eingeschränkt, was die Menge an Daten (=Images) angeht, die verwaltet werden können. Das Ding ist eher für kleine, statische Icons und sowas für die Nutzung in der Anwendung gedacht (auf Buttons, in Menüs, etc.).
hRb hat folgendes geschrieben : |
oder kann man auf die tumb.db des Verzeichnisses zugreifen (wie)? |
Ohne Details zu kennen, wie man diesen System-Image-Cache nutzt - das ist der richtige Weg, um die Performance zu steigern: du musst die Daten cachen, anders geht das kaum. :nixweiss:
cu
Narses
Delete - Do 07.12.17 18:13
- Nachträglich durch die Entwickler-Ecke gelöscht -
Sinspin - Do 07.12.17 19:39
Das wird sicher ein Interface sein dass Du bei Delphi aus einer typelib installieren kannst. Musst nur in der Windows-Doc schauen wo es sich versteckt.
Und
jaenicke war so nett schon so nett Dir die passenden Links zu liefern.
Delete - Do 07.12.17 22:18
- Nachträglich durch die Entwickler-Ecke gelöscht -
jaenicke - Fr 08.12.17 08:38
Ich hatte es gestern nicht mehr geschafft zu antworten, aber ich hatte es schon ausprobiert.
Die Übersetzung passt, ich würde allerdings out statt var benutzen. Außerdem fehlen dir noch die CLSIDs.
Und deine Enumerationen müssen Konstanten mit Integer als Zielwert sein, damit du diese auch kombinieren kannst.
Mein Vorschlag ist:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143:
| uses Winapi.ShlObj, Winapi.ActiveX;
const CLSID_LocalThumbnailCache: TGuid = '{50EF4544-AC9F-4A8E-B21B-8A26180DB13F}'; CLSID_SharedBitmap: TGuid = '{4db26476-6787-4046-b836-e8412a9e8a27}';
WTS_NONE = $00000000; WTS_EXTRACT = $00000000; WTS_INCACHEONLY = $00000001; WTS_FASTEXTRACT = $00000002; WTS_FORCEEXTRACTION = $00000004; WTS_SLOWRECLAIM = $00000008; WTS_EXTRACTDONOTCACHE = $00000020; WTS_SCALETOREQUESTEDSIZE = $00000040; WTS_SKIPFASTEXTRACT = $00000080; WTS_EXTRACTINPROC = $00000100; WTS_CROPTOSQUARE = $00000200; WTS_INSTANCESURROGATE = $00000400; WTS_REQUIRESURROGATE = $00000800; WTS_APPSTYLE = $00002000; WTS_WIDETHUMBNAILS = $00004000; WTS_IDEALCACHESIZEONLY = $00008000; WTS_SCALEUP = $00010000; WTS_DEFAULT = 0; WTS_LOWQUALITY = 1; WTS_CACHED = 2; WTSAT_UNKNOWN = 0; WTSAT_RGB = 1; WTSAT_ARGB = 2;
type WTS_FLAGS = LongInt; WTS_CACHEFLAGS = LongInt; WTS_ALPHATYPE = LongInt;
WTS_THUMBNAILID = record rgbKey: array [0 .. 15] of Byte; end;
ISharedBitmap = interface(IUnknown) ['{091162a4-bc96-411f-aae8-c5122cd03363}'] function GetSharedBitmap(out phbm: HBITMAP): HRESULT; stdcall; function GetSize(out pSize: TSize): HRESULT; stdcall; function GetFormat(out pat: WTS_ALPHATYPE): HRESULT; stdcall; function InitializeBitmap(hbm: HBITMAP; wtsAT: WTS_ALPHATYPE): HRESULT; stdcall; function Detach(out phbm: HBITMAP): HRESULT; stdcall; end;
IThumbnailCache = interface(IUnknown) ['{F676C15D-596A-4ce2-8234-33996F445DB1}'] function GetThumbnail(pShellItem: IShellItem; cxyRequestedThumbSize: UINT; flags: WTS_FLAGS; out ppvThumb: ISharedBitmap; out pOutFlags: WTS_CACHEFLAGS; out pThumbnailID: WTS_THUMBNAILID): HRESULT; stdcall; function GetThumbnailByID(thumbnailID: WTS_THUMBNAILID; cxyRequestedThumbSize: UINT; out ppvThumb: ISharedBitmap; out pOutFlags: WTS_CACHEFLAGS): HRESULT; stdcall; end;
function GetThumbnail(const AFilename: string; const ATarget: TBitmap; const ARequestedThumbSize: integer): HRESULT; type TRGBTripleArray = array[Word] of TRGBTriple; pRGBTripleArray = ^TRGBTripleArray; var ThumbnailCache: IThumbnailCache; ShellItem: IShellItem; Thumb: ISharedBitmap; OutFlags: WTS_CACHEFLAGS; ThumbnailID: WTS_THUMBNAILID; ThumbnailSize: TSize; hbm: HBITMAP; Col, Line: integer; SourceLine, TargetLine: pRGBTripleArray; Tmp: TRGBTriple; begin Result := CoInitialize(nil); if Succeeded(Result) then try Result := CoCreateInstance(CLSID_LocalThumbnailCache, nil, CLSCTX_INPROC, IThumbnailCache, ThumbnailCache); if Succeeded(Result) then begin Result := SHCreateItemFromParsingName(PChar(AFilename), nil, IShellItem, ShellItem); if Succeeded(Result) then begin Result := ThumbnailCache.GetThumbnail(ShellItem, ARequestedThumbSize, WTS_EXTRACT or WTS_SCALETOREQUESTEDSIZE, Thumb, OutFlags, ThumbnailID); if Succeeded(Result) then begin Thumb.GetSize(ThumbnailSize); Result := Thumb.GetSharedBitmap(hbm); if Succeeded(Result) then begin ATarget.SetSize(ThumbnailSize.cx, ThumbnailSize.cy); ATarget.Handle := hbm; ATarget.Dormant; ATarget.PixelFormat := pf24bit; for Line := 0 to (ATarget.Height div 2) - 1 do begin SourceLine := ATarget.ScanLine[Line]; TargetLine := ATarget.ScanLine[ATarget.Height - Line - 1]; for Col := 0 to ATarget.Width - 1 do begin Tmp := TargetLine[Col]; TargetLine[Col] := SourceLine[Col]; SourceLine[Col] := Tmp; end; end; end; end; end; end; finally CoUninitialize; end; end;
procedure TForm37.Button1Click(Sender: TObject); var Tmp: TBitmap; begin Tmp := TBitmap.Create; try if Succeeded(GetThumbnail(Edit1.Text, Tmp, Image1.Width)) then Image1.Picture.Assign(Tmp); finally Tmp.Free; end; end; |
Die optionalen Parameter können durch out nicht als nil angegeben werden. Wenn du das möchtest, musst du statt var/out direkte Pointer benutzen.
Delete - Fr 08.12.17 15:40
- Nachträglich durch die Entwickler-Ecke gelöscht -
hRb - Sa 09.12.17 13:36
Beitrag mit Interesse verfolgt. Freue mich, eine Frage gestellt zu haben, die auch andere interessiert.
Als Laie scheinen mir die Ausführungen bei Microsoft allerdings recht kompliziert oder "unscharf" zu klingen. Insbesondere wenn ab Vista von einem Cache gesprochen wird, der über den Einzel-Ordner hinaus geht (IThumbnailCache). Wie grenzt man dann wieder auf Ordneransicht ein? Und wie "füttert" man eine ImageList mit einer in der Anzahl nahezu unbegrenzten BitMaps? Andererseits klingt es hoffnungsvoll, wenn es bei MS weiter heißt: "Ihre Anwendung muss keine Implementierung des Miniaturansichtsextraktors bereitstellen".
Verstehe ich Frühlingsrolle richtig, dass er ein lauffähiges Beispiel zur Verfügung stellen will? Wäre super!
Ich könnte dann meinerseits ein Umbenenn-Tool mit einer grafischen Sortierfunktion zur Verfügung stellen. Die zeigt derzeit aus Gründen der Geschwindigkeit nur das aktive angewählte Bild mit Vorgänger und Nachfolger und befriedigt daher nicht wirklich.
hRb
jaenicke - Sa 09.12.17 14:10
hRb hat folgendes geschrieben : |
Verstehe ich Frühlingsrolle richtig, dass er ein lauffähiges Beispiel zur Verfügung stellen will? Wäre super! |
Naja... mein Beispiel ist bereits vollständig lauffähig... :gruebel:
Delete - Sa 09.12.17 18:13
- Nachträglich durch die Entwickler-Ecke gelöscht -
hRb - Mi 17.01.18 19:33
Hallo jaenicke,
ich würde das Thema gerne nochmals aufgreifen. Zunächst Danke für Dein Beispiel das ich in mein Programm eingebaut habe. Ich habe auch die Link-Texte gelesen, wenn auch nicht alles verstanden.
So bleiben eine Reihe von Fragen:
1. Es werden nur Thumbnails von Bilddateien angezeigt und nicht wie beim Explorer auch die Icon anderer Dateiendungen (exe, txt, pas etc). Liegt das an den von Dir eingestellten Parametern? Nur Feststellung - es stört mich nicht, denn meine Aufgabe lautet ja "Bilder Sortieren" und das geschieht ja nach optischen Merkmalen also Grafik-Typ.
2. Meine Frage ist eher: in welchen Container stellt man die Image-Objekte. Ich verwende derzeit eine Scrollbox und zwar zum Test fünf TImage (Größe 160x120 wie empfohlen). Für einen Ordner mit mehreren hundert Bildern müsste ich wohl dynamisch genau so viele Image-Objekte erzeugen, positionieren(left,top) und darstellen wie Anzahl Dateien. Ist dies richtig? Oder befüllt man immer nur soviele Images wie am Bildschirm darstellbar? (dann wird beim Scrollen der Vorgang wieder langsamer)
3. Bei meinem Test (5 Image) lassen sich diese
nicht positionieren, bzw
nicht mit der Maus verschieben. Derzeit stelle ich alle Dateien des Ordners in einem StringGrid dar und habe zum Verschieben zwei Button: AUF und AB. Die Image-Bilder schiebe ich dabei mit. Funktioniert, ist aber nicht sehr elegant, weil zügiges Verschieben nicht gegeben (immer nur ein Schritt).
Mir fehlt es derzeit an Ideen wie ich das "grafische Verschieben" lösen kann. Hilfe-Tips möglich? Danke im Voraus!
PS: noch eine Bemerkung an Frühlingsrolle. Bei mir sind die Ordner "Windows Kits" nicht vorhanden (Update-Opfer von WIN7 auf WIN10?)
Zitat: |
C:\Program Files (x86)\Windows Kits\8.0\Include\um
C:\Program Files (x86)\Windows Kits\8.1\Include\um |
In Original WIN10 finde ich mit leicht verändertem Pfad Ordner \um, aber der ist leer
Moderiert von Narses: Beiträge zusammengefasstIch habe vergessen und muss nach Frage nachlegen:
mein Image ist - wie beschrieben 160x120. Gleich welches Format ein Bild hat, wird das Image voll ausgefüllt, d.h ein Bild in Hochformat wird völlig verzerrt? Wie anpassen?
Delete - Do 18.01.18 10:10
- Nachträglich durch die Entwickler-Ecke gelöscht -
hRb - Do 29.03.18 15:51
Hallo,
ich musste das Thema längere Zeit ruhen lassen. Hier kurz mein derzeitiger Programm-Stand:
Nach Auswahl eines Ordners stehen in einem Stringrid die Filenamen des Ordners und alle File-Parameter wie: Datum, Uhrzeit, Dateilänge, etc. (hübsch auseinander-gedröselt). In einem Panel daneben zum Test 5 TImage und 5 Label (sie zeigen die aktive Stringgridzeile mit Vorgänger und Nachfolger an). Die Images (Bitmap) werden mit der Routine GetThumbnail von jaenicke über den Filename gefüllt, den Dateiname schreibe ich verkürzt ins dazugehörige Label. So weit so gut.
Bevor ich nun hunderte Images (Bitmap) und Label aufwändig selbst auf einer Oberfläche plaziere (genau so viele wie Dateien im Ordner), empfiehlt Frühlingsrolle
Zitat: |
Ich empfehle dir die Icons in einer TListView darzustellen. |
Hier wird einem vermutlich viel Arbeit abgenommen. In der Delphi-Hilfe liest sich dies auch alles super (Bildchen klein/groß, als Liste, usw).
Mein Problem nun: wie befülle ich das TListview-Objekt mit meinen Daten? Ich finde dort Icons aber kein TImage-Variable. Wo/wie wird Verzeichnis bzw. Filename eingetragen? Auch kann ich nicht erkennen wie die "Optik" eines List-Feldes gestaltet werden kann/muss, bzw. dass im Label nur der Dateiname (ohne Ordner) steht.
Kann jemand helfen oder gibt es irgendwo ein Beispiel, damit etwas ähnliches wie ein Explorer dabei heraus kommt?
Danke und Ostergrüße von hRb
Delete - Fr 30.03.18 07:46
- Nachträglich durch die Entwickler-Ecke gelöscht -
hRb - Mi 11.04.18 20:56
Hallo, liebe Helfer
Der Wille ein Listview korrekt zu füllem ist da, in der Umsetzung gibt es aber immer noch die eine oder andere Schwierigkeit. Um die Probleme besser darzustellen, habe ich mein Programm auf die wesentlichen Funktionen reduziert und als zip-Datei beigefügt. Nach Programmstart und Auswahl eines Ordners sieht man:
- Links ein StringGrid mit den Dateidaten des Verzeichnisses (funktioniert)
- Mittig vier Image-Objekte (zum Test) um zu zeigen, dass die benutzten Funktionen korrekt arbeiten. Nach Klick auf eine StringGridzeile werden mit Hilfe der Proceduren StringGridSelectCell und ShowImage folgendes angezeigt: die ausgewählte Datei ( mit Vorgänger, aktiv ausgewählte Datei, zwei Nachfolger). Weiterhin unter Image.Hint die Datei-Parameter (funktioniert bei allen Dateiendungen).
- Rechts das Listview-Objekt. Das Füllen mit der Procedure ButtonFuelleListViewClick funktioniert nicht korrekt. Im Test zeigt sich:
1. jpg-Hochkantformat-Bilder oder auf Quadrat zugeschnittene Dateien werden nicht angezeigt
2. bmp-Dateien werden nicht angezeigt
3. gelegentlich fehlt letzte Datei
Nach Zuweisung der ImageList an Listview sind die Count-Zeiger nicht identisch, d.h. durch das Fehlen einzelner Dateien kommt das gesamte Zähl- und Benennungssytem außer Tritt = ist falsch.
Was ist der Grund für die Differenz bzw. was mache ich falsch?
PS: ich arbeite mit Delphi 10.1.Berlin
Danke für die Geduld und evtl. Hilfe
hRb
Delete - Do 12.04.18 00:12
- Nachträglich durch die Entwickler-Ecke gelöscht -
Holgerx - Do 12.04.18 10:52
Hmm..
Hab mir das mal angeschaut (nachdem ich ein kleines bischen umgearbeitet habe für D6 ;) (Namespaces und Austausch des TFileOpenDialogs) ):
Die Funktion GetThumbnail erzeugt ein 'proportunales' Thumbnail.
Ist das Ausgangsbild bereits kleiner wie die MaxGröße, dann wird es in der originalen Größe zurück gegeben.
Wenn das resultierende Bitmap nur eine eine Größe (Höhe oder Breite) 'kleiner' hat, wie die Image-Größe in der ImageList gibt es (zumindestens in D6) eine Exception 'Ungültige Bildgröße' und es wird der ImageList nicht hinzugefügt.
Ich habe die MaxSize für das Thumnal mal auf 200 gesetzt und somit Bitmaps erzeugt, welche größer sind, wie in der ImageList. Hier wurden diese dann zwar hinzugefügt, jedoch beschnitten.
Um somit ein propotionales, eingepasstes Thumbnail zu bekommen, muss Du dieses zunächst auf ein für die ImageList passendes Bild malen und dann hinzufügen.
Hier mal eine funktionierendes Beispiel:
Hinweis:
Das eventuell doppelte Erstellen eines Thumbnail ist deshalb notwendig, da wir die Proportionen der Image-Datei erst bekommen, wenn das erste Thumbnail erstellt wurde.
Den Rahmen habe ich zum Testen um jedes Bild gezeichnet, kann also auch weggelassen werden.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45:
| function AddThumb(AFileName : string; AImageList : TImageList):boolean; var tmpThumb : TBitmap; tmpImage : TBitmap; x,y : integer; f : integer; begin Result := false; tmpImage := TBitmap.Create; try tmpImage.Width := AImageList.Width; tmpImage.Height := AImageList.Height;
tmpImage.Canvas.Rectangle(tmpImage.Canvas.ClipRect);
tmpThumb := TBitmap.Create; try if Succeeded(GetThumbnail(AFileName, tmpThumb, AImageList.Width)) then begin
if tmpThumb.Height > tmpImage.Height then begin f := Trunc((tmpThumb.Width / tmpThumb.Height) * AImageList.Height); GetThumbnail(AFileName, tmpThumb, max(f,AImageList.Height)); end;
x := (tmpImage.Width - tmpThumb.Width) div 2; y := (tmpImage.Height - tmpThumb.Height) div 2; tmpImage.Canvas.Draw(x,y,tmpThumb);
try AImageList.Add(tmpImage,nil); Result := True; except end; end; finally tmpThumb.Free; end; finally tmpImage.Free; end; end; |
Deine Stelle würde dann nur noch so aussehen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| procedure TForm1.ButtonFuelleListViewClick(Sender: TObject); var anz, i: integer; item : TListItem; s : string; ico : TIcon; begin Screen.Cursor := crHourGlass; ImageList1.Clear; Listview1.Clear; anz:= StringGrid1.RowCount-1 ; for i:=1 to anz do begin s := LabelPfad.Caption + StringGrid1.Cells[1,i]; if not AddThumb(s, ImageList1) then begin ico := TIcon.Create; try GetFileIcon(s, ico); ImageList1.AddIcon(ico); finally ico.Free; end; end; end;
ListView1.LargeImages := ImageList1; .. |
Getestet unter D6 mit GIF/BMP/JPG unterschiedlicher Größen und Proportionen..
hRb - Do 12.04.18 12:17
Hallo Holgerx,
klingt plausibel. Kannst Du bitte noch mitteilen was die Function max( ) in GetThumbnail leistet?
Zitat: |
GetThumbnail(AFileName, tmpThumb, max(f,AImageList.Height)); |
zunächst Danke. hRb
Delete - Do 12.04.18 14:54
- Nachträglich durch die Entwickler-Ecke gelöscht -
hRb - Do 12.04.18 15:00
Danke jaenicke, Funktion Max war mir unbekannt. Nach Einfügen der Uses Math funktioniert mein Programm mit den Änderungen von Holgerx bestens. Es werden nun alle Dateien angezeigt. Zumindest hatte ich auf meinem Rechner bisher noch keinen Ordner bei dem Fehler aufgetreten sind.
Allerdings - und dies bitte nicht als Kritik - durch das zweimalige Laden ist bei großen Verzeichnissen der Geschwindigkeitsverlust spürbar - zumindest im Vergleich zum Dateimanager. Es gibt also "effizientere" Methoden.
Nachtrag:
Noch ein Letztes, bevor ich dieses Thema schließe. In meinem Beispiel steht etwas versteckt noch eine zweite unbeantwortete Frage:
Während ich mit Image.Hint die Dateiparameter anzeigen kann, fehlt mir noch die Lösung beim TlistItem; dort gibt es kein Hint. Ich habe schon einiges probiert, z.B
item.SubItems.Add('Text'); Aber der Text erscheint nicht beim Zeigen aufs Item. Welche schreibweise erzeugt einen "Hint-Effekt"?
Möchte mich dieser Stelle nochmals ganz herzlich für die großartige Unterstützung bedanken !!!
MfG hRb
Delete - Do 12.04.18 16:41
- Nachträglich durch die Entwickler-Ecke gelöscht -
Holgerx - Fr 13.04.18 09:03
Hmm..
hRb hat folgendes geschrieben : |
Allerdings - und dies bitte nicht als Kritik - durch das zweimalige Laden ist bei großen Verzeichnissen der Geschwindigkeitsverlust spürbar - zumindest im Vergleich zum Dateimanager. Es gibt also "effizientere" Methoden.
|
Alles kann 'Optimiert' werden!
Jedoch haben wir anhand des Dateinamens keine Proportionen (Größe) des Bildes, um vorab zu berechnen, ob wir die Höhe oder die Breite der ImageList als Max für GetThumbnail brauchen..
Der Zweite Aufruf von GetThumbnail wird ja auch nur gemacht, wenn das Thumbnail zu hoch sein würde bei Generierung mit der Breite der ImageList...
Dies ließe sich nur optimieren, indem Du vor GetThumbNail die Größe des Bildes ermittelst, jedoch ist es hier dann meist notwendig das gesamte Bild einzulesen und auch der entsprechenden Graphic dann die Höhe und breite auszulesen.
Alternativ kannst Du natürlich eine optimierte Einlese-Routine für die 'verschiedenen' Headers der Images schreiben, um so nur immer den Anfang einzulesen. Dies jedoch dann für jedes Grafik-Format separat (BMP/JPG/PNG/GIF....).
Eine weitere Option würde sein, dass Du 'immer' ein zu großes ThumbNail generieren läst und dieses dann mit StrechDraw nochmals auf die maximale Einpassgröße runter reduzierst. Was nun wirklich schneller ist, k.A.
hRb - Fr 13.04.18 19:55
Hallo Frühlingsrolle,
Dein Vorschlag Listview.Hint zu benutzen ist eine Option. Allerdings ist hierzu ein Maus-Klick erforderlich, erfüllt also nicht ganz exakt die Hint-Funktion. Wenn die einzelnen Item kein Hint haben, müsste man wohl die Mausbewegung auszuwerten. Dies ist im Moment aber nicht mein Hauptziel.
Wer die Diskussion hier verfolgt dem sei gesagt: Auf der Basis Deines Vorschlags und der folgenden kleinen Abänderung erscheinen Dateigröße und Dateidatum als Hint-Info.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TForm1.ListView1Click(Sender: TObject); var i:integer; begin if ListView1.ItemFocused <> nil then with StringGrid1 do begin i:= ListView1.ItemIndex + 1; ListView1.Hint:= Cells[1,i] +#10 + 'Byte=' + Cells[2,i] +#10 + Cells[3,i]; end; end; |
Zum Thema Optimierung gibt es sicherlich Potential. Im Hinblick auf die erwähnten Create und Free in der Schleife der Procedure ButtonFuelleListViewClick gebe ich zu, dass ich die empfohlenen Anweisungen einfach in eine Schleife setzte. Andererseits hatte ich vor den Änderungen von Holgerx - als ich Create einmalig vor der Schleife aufrief - permanent Laufzeit-Error. Allerdings habe ich den Laufzeitfehler nicht nachhaltig untersucht. In meiner neuesten "optimierten" Version (Create nur einmal) tritt der Fehler nicht mehr auf. Werde dies beobachten!
Ansonsten bitte ich meinen Einwand zur Optimierung nicht zu ernst zu nehmen. Ich habe einen Ordner mit ca. 300 Bildern mehrfach aufgerufen und durchaus akzeptable Zeiten erreicht. Vielleicht lief beim ersten Test noch etwas im Hintergrund.
Was mir nach dem ersten Hurra allerdings noch auffällt ist, dass z.B. die Icons von Nicht-Grafikdateien in der Listview-Darstellung aufgebläht wird auf 160 x 120 Pixel, während es in der Image-Darstellung in Originalgröße (klein) bleibt. Werde mir die AddThumb-Funktion nochmal genauer ansehen, ob dies anzupassen geht.
Zunächst möchte ich aber mit Vorrang mein Hauptziel weiter verfolgen - die optische Sortierung und danach Umbennnennung von Dateien. Vielleicht kann ich demnächst ein kleines Tool vorstellen.
Gruß hRb
Holgerx - Sa 14.04.18 11:44
Hmm..
hRb hat folgendes geschrieben : |
Was mir nach dem ersten Hurra allerdings noch auffällt ist, dass z.B. die Icons von Nicht-Grafikdateien in der Listview-Darstellung aufgebläht wird auf 160 x 120 Pixel, während es in der Image-Darstellung in Originalgröße (klein) bleibt. Werde mir die AddThumb-Funktion nochmal genauer ansehen, ob dies anzupassen geht.
|
Bedenke bitte, das die Icons nicht von AddThumb erstellt werden, sondern direkt, wenn AddThumb scheitert.
Zitat: |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| if not AddThumb(s, ImageList1) then begin ico := TIcon.Create; try GetFileIcon(s, ico); ImageList1.AddIcon(ico); finally ico.Free; end; end; | |
Wenn Du hier, wie in AddThumb, das Icon auf ein Zwischen-Bitmap malen würdest, statt direkt mit AddIcon zuzuweisen, dann würde das Icon auch die Original-Größe haben, jedoch bei 32x32 Pixel auf einem 160x120 Pixel Bitmap würde dies recht klein sein.
hRb - Fr 15.06.18 22:52
Hallo Entwickler-Gemeinde,
Meine Frage ist ja schon seit geraumer Zeit beantwortet. Höchste Zeit das Thema zu schließen (werde es morgen tun). Ich habe solange gewartet,
weil Frühlingsrolle schrieb:
Zitat: |
Jetzt fehlt nur noch ein funktionstüchtiges Anwendungsbeispiel. :gruebel: |
Also habe ich getüfftelt, es liegen lassen und immer wieder verbessert. Als Anhang kann ich heute eine lauffähige Anwendung zum Sortieren und Umbenennen von Dateien beifügen. Selbstverständlich habe ich noch eine Menge Fragen zu Listview, die zu Verbesserungen führen könnten. Diese will ich wegen der Länge dieses Beitrages und zur Trennung der Probleme jedoch in getrennten Fragen stellen. Werde mich aber in den Zusatzfragen auf diese Anwendung beziehen. Vielleicht kann/will jemand das Programm selbst nutzen bevor man eine Profiprogramm kauft. (siehe Anlage).
Allen Helfern nochmals Danke. hRb
jaenicke - Sa 16.06.18 08:35
Dort könntest du übrigens gut die Ribbonbar einsetzen. Dann sähe es etwas moderner aus und du könntest die verschiedenen Möglichkeiten gruppiert unterbringen, wenn es später mehr werden.
Aber es ist schon gut gemacht, auch wenn es noch nicht viele Möglichkeiten bietet.
Was mir beim Umbenennen von Dateien fehlt sind Regular Expressions. Ohne die hilft mir solch ein Programm leider nichts. Denn damit kann ich den Dateinamen nach meinen Regeln auseinander nehmen und anders wieder zusammensetzen.
Und statt nur ganze Ordner auswählen zu können würde ich auch einfach einzelne Dateien drauf ziehen lassen.
Gut finde ich, dass du auch eine Vorschau drin hast.
hRb hat folgendes geschrieben : |
Vielleicht kann/will jemand das Programm selbst nutzen bevor man eine Profiprogramm kauft. (siehe Anlage). |
Kaufen muss man das nicht, das gibt es für private Zwecke auch kostenlos (mit Bitte um Spenden):
https://www.advancedrenamer.com
Das benutze ich mit Regular Expressions dann z.B. (als ganz einfaches Beispiel) so, diese Möglichkeit würde ich auf jeden Fall einbauen:
hRb - Sa 16.06.18 14:07
Hallo Jaenicke,
so ganz habe ich Deinen Hinweis mit den "Regular Expressions" noch nicht verstanden (Begriff noch nie gehört). Mit meiner Formel
[N6-8][N1-5][N9-30] oder [C] [N1-5][N9-30] (beachte Blank als Textzeichen dazwischen) erreiche ich das gleiche Ergebnis wie bei Deinem Beispiel. Dabei erscheint mir meine Formel etwas verständlicher. Ist allerdings nur der erste Eindruck. Muss mir das genannte Programm mal laden und genauer ansehen. (Hab ich inzwischen - jedoch nicht so genau)
Allerdings, eines sehe ich schon jetzt: Mein Hauptziel liegt nicht im Umbenennen. Ich will zuerst sortieren (Bilder) und da brauche ich für jede Datei das Vorschaubild. Das kommt beim Advanced Renamer etwas kurz. Ich werde mir aber überlegen die Ansichten komplett umzuschalten (von StringGrid auf Listview) Dann habe ich mehr Fläche zum Verschieben der Bilder und auch einige andere Probleme (siehe neue Zusatzfragen) weniger. Aber danke für Tipp.
Gruß hRb
jaenicke - Sa 16.06.18 17:38
Stell dir einfach vor du hättest folgende Dateinamen:
Test 02 - blub.txt
Einerlei 04 - auweia.txt
Obstsalatschale 08 - nix.txt
Mit der Regular Expression funktioniert das ganz genauso wie das erste Beispiel. Dein Ausdruck wird damit vermutlich aber nicht mehr funktionieren.
hRb - So 17.06.18 14:29
Hallo jaenicke, Du hast mich überzeugt. Ich hoffe in Deinem Verweis auch einen PascalCode zu finden. Gruß hRb
Sinspin - Di 19.06.18 17:11
Ich will dich auf keinen Fall davon abhalten selber, was vieleicht viel besseres, zu entwickeln, aber als weitere Inspiration schlage ich mal
Irfan View [
https://www.irfanview.com/] vor.
Du kannst Bilder, umbenenen, konvertieren, sortieren, ...
Ich bin Hobbyfotograf, über die Jahre ist einiges zusammengekommen was sortiert werden musste, ich kann mir kein Leben ohne Irfan View vorstellen. :P
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!