![]() |
Hilfe zu IThumbnailProvider
Ich würde gern ausprobieren, über IThumbnailProvider Miniaturansichten von JPG zu erstellen. Das gestaltet sich aber schwierig, im Internet findet man für Delphi kaum etwas. Bei Stackoverflow habe ich zwei Hinweise gefunden:
![]()
Delphi-Quellcode:
Es war mühsam, den ans Laufen zu bringen; ich habe IThumbnailProvider in Delphi nirgenwo gefunden und musste die Deklaration aus einer anderen Fundstelle einfügen. Letztlich bin ich dann bei
function LoadBitmapWithShellExtension(const ADllFileName: UnicodeString; const ACLSID: TCLSID;
const AFileName: UnicodeString; ASize: Integer; out AAlpha: WTS_ALPHATYPE): HBITMAP; type TDllGetClassObject = function(const CLSID, IID: TGUID; out Obj): HRESULT; stdcall; var DllModule: HMODULE; DllGetClassObject: TDllGetClassObject; ClassFactory: IClassFactory; ThumbnailProvider: IThumbnailProvider; InitializeWithFile: IInitializeWithFile; PersistFile: IPersistFile; begin DllModule := LoadLibraryW(PWideChar(ADllFileName)); if DllModule = 0 then RaiseLastOSError; try @DllGetClassObject := GetProcAddress(DllModule, 'DllGetClassObject'); if not Assigned(DllGetClassObject) then RaiseLastOSError; OleCheck(DllGetClassObject(ACLSID, IClassFactory, ClassFactory)); try OleCheck(ClassFactory.CreateInstance(nil, IThumbnailProvider, ThumbnailProvider)); try if Succeeded(ThumbnailProvider.QueryInterface(IInitializeWithFile, InitializeWithFile)) then try OleCheck(InitializeWithFile.Initialize(PWideChar(AFileName), STGM_READ)); finally InitializeWithFile := nil; end else if Succeeded(ThumbnailProvider.QueryInterface(IPersistFile, PersistFile)) then try OleCheck(PersistFile.Load(PWideChar(AFileName), STGM_READ)); finally PersistFile := nil; end else raise Exception.Create('Cannot initialize handler'); OleCheck(ThumbnailProvider.GetThumbnail(ASize, Result, AAlpha)); finally ThumbnailProvider := nil; end; finally ClassFactory := nil; end; finally FreeLibrary(DllModule); end; end;
Delphi-Quellcode:
hängengeblieben, weil mir nicht klar ist, was für
DllGetClassObject(ACLSID, IClassFactory, ClassFactory)
Delphi-Quellcode:
eingesetzt werden muss. Ich habe dann auch nicht versucht, das herauszuknobeln, weil ich bei
ACLSID
Delphi-Quellcode:
gelesen habe: Do not call DllGetClassObject directly. DllGetClassObject is exported by all ActiveX server DLLs, and it is called internally by the operating system. When a user calls CoGetClassObject (or CoCreateInstance, which internally calls CoGetClassObject) to obtain a class factory for an ActiveX object, the OLE engine loads the ActiveX server DLL into memory and calls its DllGetClassObject function. Die Umsetzung von
System.Win.ComServ.DllGetClassObject
Delphi-Quellcode:
ist mir leider auch nicht klar.
CoCreateInstance
Die zweite Stelle ist von ![]()
Delphi-Quellcode:
. Das umzusetzen habe ich aber auch keine Chance.
IInitializeWithStream
Hat vielleicht jemand den richtigen Code in der Schublade? |
AW: Hilfe zu IThumbnailProvider
Ich würde es erstmal mit {B196B28F-BAB4-101A-B69C-00AA00341D07} probieren, also der GUID von IClassFactory,
oder vermutlich {50d9450f-2a80-4f08-93b9-2eb526477d1b} Recipe Thumbnail Handler, aus der Microsoft-Demo :gruebel: ![]() oder {cf572d73-d6e5-4d45-acad-f18f4f76656f} ... schau mal, was zu IThumbnailProvider in HKEY_CLASSES_ROOT\CLSID gefunden wird. Du mußt einen Provider finden, welcher für deinen Dateityp eine Preview bietet. Als Erstes hätte ich nun Hoffnung, dass Diese auch bei den jeweiligen Dateitypen eingetragen ist. Für png, jpg und pdf hier auf die Schnelle zwar ein paar GUID darin gefunden, aber Nichts, was scheinbar mit Thumbnails zu tun hat. Da steht doch beim Hersteller beschrieben, wie das Interface aussieht? (ok, hier mal nur implizit und nicht direkt mit einer Implementation) ![]() Der Name des Interfaces ist egal, aber der heißt ja "IThumbnailProvider" und dann findet sich dort die nötige GUID, der Vorfahre und die Deklaration der einzigen Methode. Alternativ lädt man sich das WinSDK/PSDK/... runter, denn unten findest du die Headerdatei, aus der du dir die C++-Deklaration kopieren und dann nach Delphi übersetzen kannst. (alternativ im Internet nach diesem Dateinamen suchen ... PS: Microsoft hat Vieles auf Github hochgeladen) [edit] "Vieles" ist gut ... da sind inzwischen schon 5200 Repos :shock: |
AW: Hilfe zu IThumbnailProvider
Vielen Dank, Himitsu. Das Ganze ist am Rand meiner Kenntnisse, bzw. eigentlich darüber hinaus. Zudem bin ich mittlerweile im Zweifel, ob mir IThumbnailProvider eigentlich das bringt, was ich brauche, nämlich eine Miniaturansicht des JPG-Inhalts. Diese ganzen Thumbnailsachen scheinen nämlich einen quadratischen Thumbnail zurückzugeben, was etwas anderes ist.
Ich habe jetzt - nicht zuletzt aus didaktischen und auch sportlichen Gründen - intensiv weiter gesucht und ein paar Stellen gefunden, die relativ weit führen, aber eben nie einen funktionierenden Code liefern. Ich habe das Gefühl, wenn ich ein bisschen mehr in diesem Stoff stünde, dann wäre es von diesen Beispielen aus gar nicht so schwer, aber hingekriegt habe ich es einfach nicht. Natürlich als Erstes die bereits erwähnten ![]() ![]() ![]()
Delphi-Quellcode:
funktioniert auch nicht. Ein Hinweis darauf, warum nicht, findet sich in der mit Vergnügen zu lesenden
function GetPreviewHandlerCLSID(const AFileName: string): string;
![]() ![]() Ich habe mich erstmal an Postscripter gehalten und die beiden Interfaces als Klasse implementiert. Warum man die beiden
Delphi-Quellcode:
umbiegen muss -> keine Ahnung, Postscriper selbst schreibt "извращенцы", was "Perverse!" heißt. Ein paar Deklarationen habe ich eingefügt, auch wenn sie in den referenzierten Units enthalten waren, da die Units nicht immer dieselbe Deklaration hatten und auch, um unabhängig zu sein. Die Prozedur läuft auch durch, jedoch hat das Bitmap eine Breite/Länge von 0, obwohl mir das Handle plausibel aussieht. Allerdings habe ich auch keine Ahnung, womit ich die Aufrufe von
Initialize
Delphi-Quellcode:
und
GetThumbnail
Delphi-Quellcode:
eigentlich füllen soll, das sind doch API-Aufrufe?! Postscripter hat sie mit
Initialize_WS
Delphi-Quellcode:
und
Beep
Delphi-Quellcode:
gefüllt; Endgültiges steht wohl im test.rar, das ich ja nicht habe.
Showmessage('Funktioniert!'
Es ist ja klar, dass ich da herumdoktere, ohne mehr als eine Halbahnung zu haben, was ich da eigentlich tue. Wahrscheinlich kann jemand von den alten Hasen da Ordnung ins Chaos bringen. (Der Versuch,
Delphi-Quellcode:
statt
FPreviewHandler := CreateComObject
Delphi-Quellcode:
zu benutzen und damit
TComObjectFactory
Delphi-Quellcode:
durchzuführen, scheitert übrigens an "Interface not supported".)
QueryInterface
Delphi-Quellcode:
uses
... ComServ,Winapi.ActiveX, ComObj, Winapi.ShlObj, Winapi.PropSys; type {$EXTERNALSYM WTS_ALPHATYPE} WTS_ALPHATYPE = ( WTSAT_UNKNOWN = 0, WTSAT_RGB = 1, WTSAT_ARGB = 2 ); const {$EXTERNALSYM SID_IThumbnailProvider} SID_IThumbnailProvider = '{e357fccd-a995-4576-b01f-234630154e96}'; SID_IInitializeWithStream = '{b824b49d-22ac-4161-ac8a-9916e8fa3f7f}'; SID_IInitializeWithFile = '{b7d14566-0509-4cce-a71f-0a554233bd9b}'; type IThumbnailProvider = interface(IUnknown) [SID_IThumbnailProvider] function GetThumbnail(cx: UINT; var phbmp: HBITMAP; var Flags: DWORD): HResult; stdcall; end; IInitializeWithFile = interface(IUnknown) [SID_IInitializeWithFile] function Initialize(pszFilePath: PWideChar; grfMode: DWORD): HRESULT; stdcall; end; IInitializeWithStream = interface(IUnknown) [SID_IInitializeWithStream] function Initialize(const pstream: IStream; grfMode: DWORD): HRESULT; stdcall; end; TThumbnailProvider = class(TComObject, IThumbnailProvider, IInitializeWithStream, IInitializeWithFile) private protected function GetThumbnail(cx: UINT; var phbmp: HBITMAP; var Flags: DWORD): HResult; stdcall; function IInitializeWithFile.Initialize = Initialize_WF; // извращенцы function IInitializeWithStream.Initialize = Initialize_WS; function Initialize_WF(pszFilePath: PWideChar; grfMode: DWORD): HResult; stdcall; function Initialize_WS(const pstream: IStream; grfMode: DWORD): HResult; stdcall; end; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; function LoadPreviewHandler(const FileName: string):HBitmap; function ErstelleMiniatur(const FileName: string; BMPHandel:HBitmap):HBitmap; function GetPreviewHandlerCLSID(const AFileName: string): string; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var BMP:TBitmap; begin BMP := TBitmap.Create(256,256); Try BMP.Handle := ErstelleMiniatur('C:\Temp\7IV06423.JPG',BMP.Handle); Finally BMP.Free; end; end; function ErstelleMiniatur(const FileName: string; BMPHandle:HBitmap):HBitmap; var LPreviewGUID : TGUID; LInitializeWithFile : IInitializeWithFile; LInitializeWithStream : IInitializeWithStream; LInitializeWithItem : IInitializeWithItem; LIStream : IStream; LShellItem : IShellItem; FPreviewHandler : IPreviewHandler; FFileStream:TFileStream; TP:IThumbnailProvider; Alpha:WTS_ALPHATYPE; Alpha2:Cardinal; const CLSID_PhotoThumbnailProvider = '{C7657C4A-9F68-40fa-A4DF-96BC08EB3551}'; begin Result := BMPHandle; LPreviewGUID:= StringToGUID('{098f2470-bae0-11cd-b579-08002b30bfeb}'); LPreviewGUID:= StringToGUID(SID_IThumbnailProvider); LPreviewGUID:= StringToGUID(CLSID_PhotoThumbnailProvider); TComObjectFactory.Create(ComServer, TThumbnailProvider, LPreviewGUID, 'Miniatur', 'Miniatur', ciSingleInstance, tmSingle); // FPreviewHandler := CreateComObject(LPreviewGUID) As IPreviewHandler; // if (FPreviewHandler = nil) then // exit; TP := TThumbnailProvider.Create; If TP.QueryInterface(IInitializeWithStream, LInitializeWithStream) = S_OK then begin FFileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone); LIStream := TStreamAdapter.Create(FFileStream, soOwned) as IStream; LInitializeWithStream.Initialize(LIStream, STGM_READ); TP.GetThumbnail(256,Result,Alpha2); Alpha := WTS_ALPHATYPE(Alpha2); TP.Free; end; end; function TThumbnailProvider.GetThumbnail(cx: UINT; var phbmp: HBITMAP; var Flags: DWORD): HResult; begin end; function TThumbnailProvider.Initialize_WF(pszFilePath: PWideChar; grfMode: DWORD): HResult; begin end; function TThumbnailProvider.Initialize_WS(const pstream: IStream; grfMode: DWORD): HResult; begin end; |
AW: Hilfe zu IThumbnailProvider
Ich mache das (m. E. wesentlich einfacher) mit GDI+:
Delphi-Quellcode:
function GDIPMakeThumbnail(sSourceFile, sTargetFile: String;
AWidth, AHeight: Word): Boolean; var BM: tBitmap; GR: tGPGraphics; GDPImage: TGPImage; GDPThumbnail: TGPImage; H: Single; R1: Single; R2: Single; W: Single; begin Result := False; {............................................................................} if not tFile.Exists(sSourceFile) then Exit; {............................................................................} if (sTargetFile = '') or (sTargetFile = sSourceFile) then Exit; {............................................................................} if (AWidth < 10) or (AHeight < 10) then Exit; {............................................................................} BM := tBitmap.Create; BM.Width := AWidth; BM.Height := AHeight; GR := tGPGraphics.Create(BM.Canvas.Handle); GDPImage := TGPImage.Create(sSourceFile); {............................................................................} R1 := AWidth / AHeight; H := GDPImage.GetHeight; W := GDPImage.GetWidth; if (H = 0) or (W = 0) then Exit; {............................................................................} R2 := W / H; if R1 > R2 then begin W := AHeight * R2; H := AHeight; end else begin W := AWidth; H := AWidth / R2; end; {............................................................................} GDPThumbnail := GDPImage.GetThumbnailImage(Round(W), Round(H), nil, nil); GR.DrawImage(GDPThumbnail, MakeRect((AWidth - W) / 2, (AHeight - H) / 2, W, H)); try BM.SaveToFile(sTargetFile); Result := True except ShowMsg('Fehler beim Speichern der Thumbnail-Datei', ' Fehler', mb_OK, mb_IconError); end; {............................................................................} GR.Free; GDPImage.Free; GDPThumbnail.Free; BM.Free; end; |
AW: Hilfe zu IThumbnailProvider
"Diese" Thumbnails sind nunmal vorwiegend für die Vorschau im Explorer und dort sind die Icons/Images nunmal Quadrate.
|
AW: Hilfe zu IThumbnailProvider
Zitat:
![]() Bis bald... Thomas |
AW: Hilfe zu IThumbnailProvider
Zitat:
Welche GDI+-Unit verwendest du denn? Anscheinend nicht die von Erik van Bilsen. @Himitsu: Ja, das habe ich ein bisschen spät bemerkt. Allerdings ging es mir dann immer mehr um den "sportlichen" Aspekt, ich wollte das Ganze zumindest einmal ans Laufen bringen und dabei auch noch verstehen. @mytbo: Vielen Dank. Eine Eigenart dieser reinen Thumbnail-Prozessoren ist, dass sie bei JPG-Dateien nachschauen, ob es ein Thumbnail gibt und dann verwenden sie das. Für größere Miniaturbilder ist das von der Qualität her nicht akzeptabel. Meine gegenwärtige Lösung arbeitet mit IExtractImage aus Winapi.ShlObj und das funktioniert gut. Ich wollte unter anderem aber auch mal sehen, ob die neueren Methoden vielleicht schneller sind. |
AW: Hilfe zu IThumbnailProvider
Vielleicht ist es einfacher, sich über IShellFolder und IShellIcon oder IExtractIcon das Vorschau-Icon zu besorgen?
|
AW: Hilfe zu IThumbnailProvider
|
AW: Hilfe zu IThumbnailProvider
Zitat:
Das ist die von Prodigy. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:59 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz