Autor Beitrag
hRb
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 132
Erhaltene Danke: 3



BeitragVerfasst: Mo 04.12.17 16:06 
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):
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 9873
Erhaltene Danke: 1052

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.1
BeitragVerfasst: Mo 04.12.17 17:15 
Moin!

user profile iconhRb hat folgendes geschrieben Zum zitierten Posting springen:
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.).

user profile iconhRb hat folgendes geschrieben Zum zitierten Posting springen:
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

_________________
There are 10 types of people - those who understand binary and those who don´t.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18659
Erhaltene Danke: 1608

W10 x64 (Chrome, IE11)
Delphi 10.2 Ent, Oxygene, C# (VS 2015), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 07.12.17 12:28 
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Ohne Details zu kennen, wie man diesen System-Image-Cache nutzt
Zum Glück gibt es eine entsprechende Doku für die API. ;-)

Schon in Win2k gab es IExtractImage:
msdn.microsoft.com/e...esktop/bb761848.aspx

Ich würde aber eher die ab Vista mit den ganzen neuen APIs verfügbare Thumbnail Cache API (via IThumbnailCache usw.) benutzen:
msdn.microsoft.com/e...esktop/bb774628.aspx

Alternativ gibt es noch IShellItemImageFactory, aber da bekommst du nur ein HBITMAP während IThumbnailCache noch mehr Informationen zu dem Bild liefert:
msdn.microsoft.com/e...esktop/bb761084.aspx

_________________
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!

Für diesen Beitrag haben gedankt: Frühlingsrolle, Narses
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2054
Erhaltene Danke: 376

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Do 07.12.17 18:13 
@ jaenicke

Hat Delphi 10.1 die Schnittstellen in irgendeiner Unit deklariert? Das IThumbnailCache würde ich gerne testen.
Gemäß der Doku, zu finden (ab Vista) in der Thumbcache.h und Thumbcache.idl (beides mit einem Texteditor öffnen), siehe:

ausblenden unter Win7 x64
1:
2:
C:\Program Files (x86)\Windows Kits\8.0\Include\um
C:\Program Files (x86)\Windows Kits\8.1\Include\um

Die Schnittstelle müsste man ansonsten entsprechend nachbauen.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1106
Erhaltene Danke: 70

Win7
DXE2 Prof, Lazarus
BeitragVerfasst: 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 user profile iconjaenicke war so nett schon so nett Dir die passenden Links zu liefern.

_________________
Solange keine Zeile Code geschrieben ist, läuft ein Programm immer fehlerfrei.
Ich teste nicht, weil ich Angst habe Fehler zu finden.
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2054
Erhaltene Danke: 376

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Do 07.12.17 22:18 
Ok. Und welche Typbibliothek wäre das deiner Meinung nach?

Nachtrag

Meine Übersetzung der Thumbcache.idl nach Pascal (relevante Teil zum IThumbnailCache):

ausblenden volle Höhe 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:
uses
  Windows, ShlObj;

type
  WTS_FLAGS = (
    WTS_NONE                 = $00000000,
    WTS_EXTRACT              = $00000000,  // Extract the thumbnail if it is not cached.
    WTS_INCACHEONLY          = $00000001,  // Only return the thumbnail if it is cached.
    WTS_FASTEXTRACT          = $00000002,  // If not cached, only extract the thumbnail if it is embedded in EXIF format, typically 160x120.
    WTS_FORCEEXTRACTION      = $00000004,  // Ignore cache and extract thumbnail from source file.
    WTS_SLOWRECLAIM          = $00000008,  // Thumbnail has an extended lifetime. Use for volumes that might go offline, like non-fixed disks.
    WTS_EXTRACTDONOTCACHE    = $00000020,  // Extract but do not add to cache.
    WTS_SCALETOREQUESTEDSIZE = $00000040,  // Windows 7 and later. If necessary, shrink the bitmap (preserving aspect ratio) so width and height fit the given size.
    WTS_SKIPFASTEXTRACT      = $00000080,  // Windows 7 and later. Do not attempt to extract the thumbnail embedded in EXIF format.
    WTS_EXTRACTINPROC        = $00000100,  // Windows 7 and later. Run the thumbnail extractor InProc. Use for debugging thumbnail extractors.
    WTS_CROPTOSQUARE         = $00000200,  // Windows 8 and later. If necessary, crop the bitmap to a square.
    WTS_INSTANCESURROGATE    = $00000400,  // Windows 8 and later. Create a surrogate for this instance of the cache, rather than using the shared dllhost surrogate
    WTS_REQUIRESURROGATE     = $00000800,  // Windows 8 and later. Require extractions to take place in the surrogate
    WTS_APPSTYLE             = $00002000,  // Windows 8 and later. Pass the App-style flag to IThumbnailSettings if the provider supports it.
    WTS_WIDETHUMBNAILS       = $00004000,  // Windows 8 and later. Stretch and crop the bitmap to a .7 aspect ratio.
    WTS_IDEALCACHESIZEONLY   = $00008000,  // Windows 8 and later. Return from the ideal cache snap size only. The returned image may still be larger but it will be pulled from the correct cache entry
    WTS_SCALEUP              = $00010000   // Windows 8 and later. If necessary, stretch the bitmap so width and height fit the given size.
  );

  WTS_CACHEFLAGS = (
    WTS_DEFAULT = 0,
    WTS_LOWQUALITY,
    WTS_CACHED
  );

  WTS_ALPHATYPE = (
    WTSAT_UNKNOWN = 0,
    WTSAT_RGB,
    WTSAT_ARGB
  );

  WTS_THUMBNAILID = record
    rgbKey: array[0..15of Byte;
  end;

  // This interface is used as a thin wrapper around HBITMAP objects.  It allows an
  // HBITMAP to be ref-counted and protected from having its underlying data be changed
  ISharedBitmap = interface(IUnknown)
    ['{091162a4-bc96-411f-aae8-c5122cd03363}']
    function GetSharedBitmap(var phbm: HBITMAP): HRESULT; stdcall;
    function GetSize(var pSize: TSize): HRESULT; stdcall;
    function GetFormat(var pat: WTS_ALPHATYPE): HRESULT; stdcall;
    function InitializeBitmap(hbm: HBITMAP; wtsAT: WTS_ALPHATYPE): HRESULT; stdcall;
    function Detach(var phbm: HBITMAP): HRESULT; stdcall;
  end;

  // Interface for the system thumbnail cache.  GetThumbnail is used to extract and return
  // thumbnails for IShellItems.  The cache behavior can be specified using one or more of
  // the WTS_FLAGS.  GetThumbnailID allows the caller to retrieve an image known to be in
  // the cache via its ID (which was returned by GetThumbnail).
  IThumbnailCache = interface(IUnknown)
    ['{F676C15D-596A-4ce2-8234-33996F445DB1}']
    function GetThumbnail(pShellItem: IShellItem; cxyRequestedThumbSize: UINT;
      flags: WTS_FLAGS; var ppvThumb: ISharedBitmap; var pOutFlags: WTS_CACHEFLAGS;
      var pThumbnailID: WTS_THUMBNAILID): HRESULT; stdcall;
    function GetThumbnailByID(thumbnailID: WTS_THUMBNAILID; cxyRequestedThumbSize: UINT;
      var ppvThumb: ISharedBitmap; var pOutFlags: WTS_CACHEFLAGS): HRESULT; stdcall;
  end;

Jetzt fehlt nur noch ein funktionstüchtiges Anwendungsbeispiel. :gruebel:

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18659
Erhaltene Danke: 1608

W10 x64 (Chrome, IE11)
Delphi 10.2 Ent, Oxygene, C# (VS 2015), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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:
ausblenden volle Höhe 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// Extract the thumbnail if it is not cached.
  WTS_INCACHEONLY = $00000001// Only return the thumbnail if it is cached.
  WTS_FASTEXTRACT = $00000002// If not cached, only extract the thumbnail if it is embedded in EXIF format, typically 160x120.
  WTS_FORCEEXTRACTION = $00000004// Ignore cache and extract thumbnail from source file.
  WTS_SLOWRECLAIM = $00000008;
  // Thumbnail has an extended lifetime. Use for volumes that might go offline, like non-fixed disks.
  WTS_EXTRACTDONOTCACHE = $00000020// Extract but do not add to cache.
  WTS_SCALETOREQUESTEDSIZE = $00000040;
  // Windows 7 and later. If necessary, shrink the bitmap (preserving aspect ratio) so width and height fit the given size.
  WTS_SKIPFASTEXTRACT = $00000080// Windows 7 and later. Do not attempt to extract the thumbnail embedded in EXIF format.
  WTS_EXTRACTINPROC = $00000100;
  // Windows 7 and later. Run the thumbnail extractor InProc. Use for debugging thumbnail extractors.
  WTS_CROPTOSQUARE = $00000200// Windows 8 and later. If necessary; crop the bitmap to a square.
  WTS_INSTANCESURROGATE = $00000400;
  // Windows 8 and later. Create a surrogate for this instance of the cache; rather than using the shared dllhost surrogate
  WTS_REQUIRESURROGATE = $00000800// Windows 8 and later. Require extractions to take place in the surrogate
  WTS_APPSTYLE = $00002000// Windows 8 and later. Pass the App-style flag to IThumbnailSettings if the provider supports it.
  WTS_WIDETHUMBNAILS = $00004000// Windows 8 and later. Stretch and crop the bitmap to a .7 aspect ratio.
  WTS_IDEALCACHESIZEONLY = $00008000;
  // Windows 8 and later. Return from the ideal cache snap size only. The returned image may still be larger but it will be pulled from the correct cache entry
  WTS_SCALEUP = $00010000// Windows 8 and later. If necessary, stretch the bitmap so width and height fit the given size.

  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 .. 15of Byte;
  end;

  // This interface is used as a thin wrapper around HBITMAP objects.  It allows an
  // HBITMAP to be ref-counted and protected from having its underlying data be changed
  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;

  // Interface for the system thumbnail cache.  GetThumbnail is used to extract and return
  // thumbnails for IShellItems.  The cache behavior can be specified using one or more of
  // the WTS_FLAGS.  GetThumbnailID allows the caller to retrieve an image known to be in
  // the cache via its ID (which was returned by GetThumbnail).
  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: stringconst 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;
              // Dormant --> make own DDB bitmap to be independant from DIB bitmap in handle (can be freed afterwards)

              // Now we need to flip the image vertically because it is provided upside down
              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.

_________________
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!

Für diesen Beitrag haben gedankt: Frühlingsrolle, Sinspin
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2054
Erhaltene Danke: 376

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Fr 08.12.17 15:40 
Vielen Dank für das Beispiel, jaenicke!
Ich nehm' gleich die Anpassungen vor.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 132
Erhaltene Danke: 3



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18659
Erhaltene Danke: 1608

W10 x64 (Chrome, IE11)
Delphi 10.2 Ent, Oxygene, C# (VS 2015), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 09.12.17 14:10 
user profile iconhRb hat folgendes geschrieben Zum zitierten Posting springen:
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:

_________________
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2054
Erhaltene Danke: 376

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Sa 09.12.17 18:13 
Frühlingsrolle hat nur gezeigt, wie ein solches Interface/Schnittstelle aus der MSDN Doku in Delphi übernommen werden kann. Die Schnittstelle macht bis dahin nichts.
Wie sie zu nutzen ist, hat jaenicke in seiner GetThumbnail() Methode schön dargestellt.
So und so ähnlich könntest auch du ganz selbstständig mit den anderen verlinkten Beiträgen verfahren.
Für dein Anliegen jeodch reicht der Ansatz, den jaenicke zur Verfügung gestellt hat.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 132
Erhaltene Danke: 3



BeitragVerfasst: 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 user profile iconNarses: Beiträge zusammengefasst

Ich 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?
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2054
Erhaltene Danke: 376

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Do 18.01.18 10:10 
Zitat:
Bei mir sind die Ordner "Windows Kits" nicht vorhanden [...] In Original WIN10 finde ich mit leicht verändertem Pfad Ordner \um, aber der ist leer

Wird die Windows SDK installiert, dann sollten auch die Dateien vorzufinden sein. Ich habe wahrscheinlich die SDK zusammen mit Visual Studio installiert und daher auch die Gegebenheit.

Zitat:
Es werden nur Thumbnails von Bilddateien angezeigt und nicht wie beim Explorer auch die Icon anderer Dateiendungen (exe, txt, pas etc)

Dafür könntest du z.B. die Funktion SHGetFileInfo() nutzen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
uses ShellAPI;

procedure GetFileIcon(AFileName: string; Output: TIcon);
var
  shInfo: TSHFileInfo;
begin
  SHGetFileInfo(PChar(AFileName), 0, shInfo, SizeOf(shInfo), SHGFI_ICON or SHGFI_LARGEICON); // SHGFI_LARGEICON = 32x32 px großes Icon. Größer geht's nicht.
  Output.Handle := shInfo.hIcon;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ico: TIcon;
begin
  ico := TIcon.Create;
  try
    GetFileIcon(Application.ExeName, ico); // gibt das Icon der momentanen Anwendung (.EXE) aus. Geht genauso gut mit .PAS, .TXT usw. 
    Image1.Picture.Icon.Assign(ico);
  finally
    ico.Free;
  end;
end;

Eine andere Möglichkeit wäre ExtractIcon(), jedoch beschränkt sich die Methode nur auf Dateiendungen - .EXE, .DLL und .ICO.

Ich empfehle dir die Icons in einer TListView darzustellen. Mit der Eigenschaft .ViewStyle kannst du die Darstellung entsprechend anpassen, ob nun mit Text (vsReport) oder nur mit Icons (vsIcon, vsLargeIcon). Bedenke, dass in der Ansicht vsReport die Icons nur in der ersten Spalte angezeigt werden können.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 132
Erhaltene Danke: 3



BeitragVerfasst: 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
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2054
Erhaltene Danke: 376

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Fr 30.03.18 07:46 
Guten Morgen hRb,

TListView sieht dafür eine ImageList vor. Dafür müssten die TBitmap-Objekte mit: ImageList.Add(bmpObj, nil); aufgenommen werden.
Davor sollte noch die Größe (.Width, .Height) der ImageList festgelegt werden.
Diese weist du der TListView zu: ListView.LargeImages := ImageList;
und fügst Einträge samt Grafik wie folgt ein:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
var
  item: TListItem;
  i: Integer;
begin
  ListView.Clear;
  for i := 0 to ImageList.Count - 1 do
  begin
    item := ListView.Items.Add;
    item.Caption := IntToStr(i);
    item.ImageIndex := i;
  end;
end;

Die dafür vorgesehene Darstellung (wie im Explorer) wäre: ListView.ViewStyle := vsIcon;

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 132
Erhaltene Danke: 3



BeitragVerfasst: 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
Einloggen, um Attachments anzusehen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2054
Erhaltene Danke: 376

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Do 12.04.18 00:12 
Interessant. Bei mir werden wohl Hochkantbilder im BMP, JPG und PNG Format in der ListView angezeigt, aber leider nicht alle. In einem Ordner habe ich um die 120 Bilder. Davon werden nur die ersten 69 in der ListView dargestellt (ohne dass dazwischen eins ausgelassen wird).
Es liegt nahe, dass etwas falsch gezählt wird. Schaue ich mir heute auf jeden Fall an.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
Holgerx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 42
Erhaltene Danke: 15

Win95 - Win8.1 / MSServer2000 - MSServer2012
Delphi 6pro / XE4
BeitragVerfasst: 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.
ausblenden volle Höhe 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
      // Erstmal mit der Breite, um die Proportionen des Bildes zu bekommen
      if Succeeded(GetThumbnail(AFileName, tmpThumb, AImageList.Width)) then begin

        // Wenn Thumb nun zu Hoch..
        if tmpThumb.Height > tmpImage.Height then begin
          f := Trunc((tmpThumb.Width / tmpThumb.Height) * AImageList.Height);
          GetThumbnail(AFileName, tmpThumb, max(f,AImageList.Height));
        end;

        // Zentriert auf dem Sollimage Zeichnen
        x := (tmpImage.Width - tmpThumb.Width) div 2;
        y := (tmpImage.Height - tmpThumb.Height) div 2;
        tmpImage.Canvas.Draw(x,y,tmpThumb);

        try
          // Zur ImageList hinzufügen
          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:

ausblenden 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{-FixRow} ;
  // alle Bilder in ImageList einfügen
  for i:=1 to anz do
  begin
    s := LabelPfad.Caption + StringGrid1.Cells[1,i];
    if not AddThumb(s, ImageList1) then
    begin // Icon der Nicht-Grafik-Datei  nach Frühlingsrolle
      ico := TIcon.Create;
      try
        GetFileIcon(s, ico); // gibt das Icon der momentanen Anwendung
        ImageList1.AddIcon(ico);
      finally
        ico.Free;
      end;
    end;
  end;

  ListView1.LargeImages := ImageList1;  // ImageList zuweisen
  ..



Getestet unter D6 mit GIF/BMP/JPG unterschiedlicher Größen und Proportionen..
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 132
Erhaltene Danke: 3



BeitragVerfasst: 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
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18659
Erhaltene Danke: 1608

W10 x64 (Chrome, IE11)
Delphi 10.2 Ent, Oxygene, C# (VS 2015), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 12.04.18 12:20 
user profile iconhRb hat folgendes geschrieben Zum zitierten Posting springen:
Kannst Du bitte noch mitteilen was die Function max( ) in GetThumbnail leistet?
Siehe Doku:
docwiki.embarcadero....o/de/System.Math.Max
Die Funktion gibt den größeren Wert zurück, entweder f oder AImageList.Height, je nachdem welcher größer ist.

_________________
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!