KaFu Posted December 18, 2010 Share Posted December 18, 2010 (edited) HiHo Forum,for quite some time now I've tried to extract shell thumbnail previews of files. The way to go seems to be the IExtractImage interface. But how to access that one? I've found quite a good tutorial for delphi here (google cache as the website seems to be down).Retrieving the files PIDL seems quite straight forward using Yashieds WinApiEx functions (step 1+2). But then the hard part, how to access the interface itself? AutoItObject might be the right tool for this, but... as already stated in the title I've clearly not understood AutoItObject (yet) ...Maybe one of the (real) pros is willing to take a deeper look?expandcollapse popup#cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.6.1 Author: KaFu Script Function: IExtracteImage Shell Interface Example #ce ---------------------------------------------------------------------------- #include <WinApiEx.au3> $sFile_BMP_Path = StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", 0, -1)) & "Examples\GUI\Advanced\Images\" $sFile_BMP_File = $sFile_BMP_Path & "Blue.bmp" #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> GUICreate("IExtractImage Example") GUICtrlCreatePic($sFile_BMP_File, 10, 10) #cs ; http://webcache.googleusercontent.com/search?q=cache:Ta2k4JCcIbQJ:www.delphi3000.com/article.asp%3FID%3D3806+iextractimage+c&cd=8&hl=de&ct=clnk&gl=de&client=firefox-a IExtractImage Interface Type Declaration ============ MIDL_INTERFACE("BB2E617C-0920-11d1-9A0B-00C04FC2D6C1") IExtractImage : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetLocation( /* [size_is][out] */ LPWSTR pszPathBuffer, /* [in] */ DWORD cch, /* [unique][out][in] */ DWORD *pdwPriority, /* [in] */ const SIZE *prgSize, /* [in] */ DWORD dwRecClrDepth, /* [in] */ DWORD *pdwFlags) = 0; virtual HRESULT STDMETHODCALLTYPE Extract( /* [out] */ HBITMAP *phBmpThumbnail) = 0; }; #ce #cs Step #1: Retrieving IShellFolder Interface Pointer (skipped) Step #2: Retrieving Relative PIDL for A System File (done directly via _WinApiEx calls below (?) #ce $hPath_PIDL = _WinAPI_ShellILCreateFromPath($sFile_BMP_File) ConsoleWrite(@error & @TAB & $hPath_PIDL & @CRLF) ConsoleWrite(_WinAPI_ShellGetPathFromIDList($hPath_PIDL) & @CRLF) #cs ============ Step #3: Retrieving IExtractImage Interface Pointer from ShellFolder Now to really get the IExtractImage interface pointer, we use IShellFolder's method: GetUIObjectOf(). This is the method to obtain an aforementioned indirectly-exposed interface from IShellFolder interface. TargetFolder.GetUIObjectOf(0, 1, ItemIDList, IExtractImage, nil, XtractImg); Malloc.Free(ItemIDList); ============ Step #4: Final Step - IExtractImage In Action Once we obtain an IExtractImage interface pointer, there are two steps to the process. First, use GetLocation() to request the path description of an image and specify how the image should be rendered. Then, call Extract() to extract the image. var ... Bmp: TBitmap; BitmapHandle: HBITMAP; Buf: array[0..MAX_PATH] of WideChar; ColorDepth, Priority, Flags: DWORD; begin ... { Specify thumbnail image size we want. We want the image to fit the size of TImage component. } Size.cx := Image1.Width; // desired thumbnail image width Size.cy := Image1.Height; // desired thumnbail image height { Specify Flag bits for GetLocation() method. } Flags := IEIFLAG_SCREEN // Used to tell the object to render or // as if for the screen. IEIFLAG_OFFLINE; // Used to tell the object to use // only local content for rendering. Priority := 0; // normal priority. usefull if extraction // process executed within background thread ColorDepth := 32; // we want thumbnail image of type pf32bit GetLocationRes := XtractImg.GetLocation(Buf, sizeof(Buf), Priority, Size, ColorDepth, Flags); if (GetLocationRes = NOERROR) or (GetLocationRes = E_PENDING) then begin Bmp := TBitmap.Create; try OleCheck(XtractImg.Extract(BitmapHandle)); Bmp.Handle := BitmapHandle; Image1.Picture.Assign(Bmp); finally Bmp.Free; end; end; ... #ce $iRes = _WinAPI_CoTaskMemFree($hPath_PIDL) ConsoleWrite(@error & @TAB & $iRes & @CRLF) GUISetState(@SW_SHOW) While 1 $msg = GUIGetMsg() If $msg = $GUI_EVENT_CLOSE Then ExitLoop WEnd GUIDelete()Regards Edited December 19, 2010 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
trancexx Posted December 18, 2010 Share Posted December 18, 2010 (edited) Follow that tutorial precisely (all steps) and there will be no problems. Add code shortcuts later. The biggest job is to define the interfaces. After that it's nothing but joy. You need IShellFolder and IExtractImage, meaning $dtagIShellFolder and $dtagIExtractImage. Edited December 18, 2010 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
KaFu Posted December 18, 2010 Author Share Posted December 18, 2010 (edited) Okay, went back to step 1 . Retrieved the IShellFolder interface for the desktop folder and defined the $tagIShellFolder. But how do I glue this together to form an object ? expandcollapse popup#include "AutoItObject.au3" _AutoItObject_Startup() ; Step by Step Tutorial for IExtractImage in Delphi ; http://webcache.googleusercontent.com/search?q=cache:Ta2k4JCcIbQJ:www.delphi3000.com/article.asp%3FID%3D3806+iextractimage+c&cd=8&hl=de&ct=clnk&gl=de&client=firefox-a ; Step #1: Retrieving IShellFolder Interface Pointer $strIShellFolder = DllStructCreate("ptr;") $p_strIShellFolder = DllStructGetPtr($strIShellFolder) ; SHGetDesktopFolder = http://msdn.microsoft.com/de-de/library/bb762175%28v=VS.85%29.aspx $iRes = DllCall("shell32.dll", "int", "SHGetDesktopFolder", "ptr", $p_strIShellFolder) ConsoleWrite($iRes[0] & @TAB & DllStructGetData($strIShellFolder, 1) & @CRLF) ; IShellFolder Interface = http://msdn.microsoft.com/de-de/library/bb775075%28v=VS.85%29.aspx $tagIShellFolder = "QueryInterface long(ptr;ptr;ptr);" & _ "AddRef ulong();" & _ "Release ulong();" & _ "BindToObject hresult(hwnd);" & _ "BindToStorage hresult(hwnd);" & _ "CompareIDs hresult(hwnd);" & _ "CreateViewObject hresult(hwnd);" & _ "EnumObjects hresult(hwnd);" & _ "GetAttributesOf hresult(hwnd);" & _ "GetDisplayNameOf hresult(hwnd);" & _ "GetUIObjectOf hresult(hwnd);" & _ "ParseDisplayName hresult(hwnd);" & _ "SetNameOf hresult(hwnd);" ; http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/05884106-9acd-4213-8f1d-1e6b1bba9262 $IID_IShellFolder = _AutoItObject_CLSIDFromString("{000214E6-0000-0000-C000-000000000046}") $oIShellFolder = _AutoItObject_ObjCreate($IID_IShellFolder, $IID_IShellFolder, $tagIShellFolder) $strReceiver = DllStructCreate("ptr;") ; ParseDisplayName = http://msdn.microsoft.com/de-de/library/bb775090%28v=VS.85%29.aspx $oIShellFolder.ParseDisplayName(0, "", "c:\windows", 0, DllStructGetPtr($strReceiver), 0) ConsoleWrite(DllStructGetData($strReceiver, 1) & @CRLF) $oIShellFolder = 0 _AutoItObject_Shutdown() Edited December 18, 2010 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
ProgAndy Posted December 19, 2010 Share Posted December 19, 2010 (edited) I just created an example yesterday. Not very clean but hey, it works. expandcollapse popup#include<AutoItObject.au3> #include<WinAPI.au3> #include<WinAPIEx.au3> #include<WindowsConstants.au3> #include<Constants.au3> #include<GUIConstantsEx.au3> #include-once ;=============================================================================== #API "Extracting Image" ; IShellFolder ; IExtractImage ;=============================================================================== ;.......written by ProgAndy ;=============================================================================== #interface "IShellFolder" $sIID_IShellFolder = "{000214E6-0000-0000-C000-000000000046}" ; Definition Global Const $dtagIShellFolder = $dtagIUnknown & _ "ParseDisplayName hresult(hwnd;ptr;wstr;dword*;ptr*;dword*);" & _ "EnumObjects hresult(hwnd;dword;ptr*);" & _ "BindToObject hresult(ptr;ptr;ptr;ptr*);" & _ "BindToStorage hresult(ptr;ptr;ptr;ptr*);" & _ "CompareIDs hresult(lparam;ptr;ptr);" & _ "CreateViewObject hresult(hwnd;ptr;ptr*);" & _ "GetAttributesOf hresult(UINT;ptr;ulong*);" & _ "GetUIObjectOf hresult(hwnd;uint;ptr;ptr;uint*;ptr*);" & _ "GetDisplayNameOf hresult(ptr;uint;ptr);" & _ "SetNameOf hresult(hwnd;ptr;wstr;dword;ptr*);" ; List Global Const $ltagIShellFolder = $ltagIUnknown & _ "ParseDisplayName;" & _ "EnumObjects;" & _ "BindToObject;" & _ "BindToStorage;" & _ "CompareIDs;" & _ "CreateViewObject;" & _ "GetAttributesOf;" & _ "GetUIObjectOf;" & _ "GetDisplayNameOf;" & _ "SetNameOf;" ;=============================================================================== ;=============================================================================== #interface "IExtractImage" Global Const $sIID_IExtractImage = "{BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}" ; Definition Global Const $dtagIExtractImage = $dtagIUnknown & _ "GetLocation hresult(wstr;DWORD;DWORD*;ptr;dword;DWORD*);" & _ "Extract hresult(ptr*);" ; List Global Const $ltagIExtractImage = $ltagIUnknown & _ "GetLocation;" & _ "Extract;" ;=============================================================================== ;=============================================================================== #interface "IShellItemImageFactory" Global Const $sIID_IShellItemImageFactory = "{bcc18b79-ba16-442f-80c4-8a59c30c463b}" ; Definition Global Const $dtagIShellItemImageFactory = $dtagIUnknown & _ "GetImage hresult(uint64;dword;ptr*);" ; <==== uint64 instead of long;long ; List Global Const $ltagIShellItemImageFactory = $ltagIUnknown & _ "GetImage;" ;=============================================================================== ;=============================================================================== #interface "IShellItem" Global Const $IID_IShellItem = "{43826d1e-e718-42ee-bc55-a1e261c37bfe}" Global Const $dtagIShellItem = $dtagIUnknown & _ "BindToHandler hresult(ptr;ptr;ptr;ptr*);" & _ "GetParent hresult(ptr*);" & _ "GetDisplayName hresult(dword;ptr*);" & _ "GetAttributes hresult(dword;dword*);" & _ "Compare hresult(ptr;dword;int*);" Global Const $ltagIShellItem = $ltagIUnknown & _ "BindToHandler;" & _ "GetParent;" & _ "GetDisplayName;" & _ "GetAttributes;" & _ "Compare;" ;=============================================================================== Global $hDCB, $hBmp _AutoItObject_StartUp() OnAutoItExitRegister("_close") Func _close() _WinAPI_DeleteDC($hDCB) _WinAPI_DeleteObject($hBmp) _AutoItObject_Shutdown() EndFunc ;==>_close $fUseAlphaBlend = False $sFileName = "D:\Eigene Bilder\test.png" $tIIDImgFact = _AutoItObject_CLSIDFromString($sIID_IShellItemImageFactory) Dim $pImgFact If 0 = _SHCreateItemFromParsingName($sFileName, 0, DllStructGetPtr($tIIDImgFact), $pImgFact) And $pImgFact Then $IImgFact = _AutoItObject_WrapperCreate($pImgFact, $dtagIShellItemImageFactory) $r = $IImgFact.GetImage(_MakeUINT64(128, 128), 0, 0) ; <==== _MakeUINT64 added $hBmp = $r[3] ; <==== parameter count was changed, so fixed it here Else $pidl = _ILCreateFromPath($sFileName) Dim $pIShellFolder, $pRelative $tRIID = _AutoItObject_CLSIDFromString($sIID_IShellFolder) $tRIIDExtract = _AutoItObject_CLSIDFromString($sIID_IExtractImage) If StringInStr(FileGetAttrib($sFileName), "D", 1) Then MsgBox(0, '', "Cannot create preview for Folders on Windows prior to Vista") Exit Else _SHBindToParent($pidl, DllStructGetPtr($tRIID), $pIShellFolder, $pRelative) $IShellFolder = _AutoItObject_WrapperCreate($pIShellFolder, $dtagIShellFolder) $tSTRRET = DllStructCreate("uint uType;ptr data;") $r = $IShellFolder.GetDisplayNameOf(Number($pRelative), 0, Number(DllStructGetPtr($tSTRRET))) Dim $name _StrRetToBuf(DllStructGetPtr($tSTRRET), 0, $name, 512) $tSTRRET = 0 MsgBox(0, 'name of item', $name) $tArray = DllStructCreate("ptr") DllStructSetData($tArray, 1, $pRelative) $r = $IShellFolder.GetUIObjectOf(0, 1, Number(DllStructGetPtr($tArray)), Number(DllStructGetPtr($tRIIDExtract)), 0, 0) $IExtractImage = _AutoItObject_WrapperCreate($r[6], $dtagIExtractImage) EndIf $tSize = DllStructCreate("long;long") DllStructSetData($tSize, 1, 128) DllStructSetData($tSize, 2, 128) $r = $IExtractImage.GetLocation("", 1024, 0, Number(DllStructGetPtr($tSize)), 32, 0) MsgBox(0, '', $r[1]) $r = $IExtractImage.Extract(0) $hBmp = $r[1] $IShellFolder = 0 _CoTaskMemFree($pidl) EndIf $hGUI = GUICreate("test", 256, 128) GUIRegisterMsg($WM_PAINT, "_WM_PAINT") $btnColor = GUICtrlCreateButton("ColorChange", 130, 20, 100, 20) $hDC = _WinAPI_GetDC(0) $hDCB = _WinAPI_CreateCompatibleDC($hDC) _WinAPI_SelectObject($hDCB, $hBmp) _WinAPI_ReleaseDC(0, $hDC) $IExtractImage = 0 GUISetState() While 1 Switch GUIGetMsg() Case -3 ExitLoop Case $btnColor GUISetBkColor(Random(0, 0xFFFFFF, 1)) EndSwitch WEnd Func _WM_PAINT($hWnd, $uMsg, $wParam, $lParam) Local $tPS Local $hDC = _WinAPI_BeginPaint($hWnd, $tPS) $x = DllStructGetData($tPS, "rPaint", 1) $y = DllStructGetData($tPS, "rPaint", 2) $w = DllStructGetData($tPS, "rPaint", 3) - $x $h = DllStructGetData($tPS, "rPaint", 4) - $y If $x <= 128 Then If $x + $w > 128 Then $w = 128 - $x If $fUseAlphaBlend Then _WinAPI_AlphaBlend($hDC, $x, $y, $w, $h, $hDCB, $x, $y, $w, $h, 255, True) Else _WinAPI_BitBlt($hDC, $x, $y, $w, $h, $hDCB, $x, $y, $SRCCOPY) EndIf EndIf _WinAPI_EndPaint($hWnd, $tPS) Return $GUI_RUNDEFMSG EndFunc ;==>_WM_PAINT Func _MakeUINT64($long1, $long2) Local $d = DllStructCreate("align 4;dword[2]") DllStructSetData($d, 1, $long1, 1) DllStructSetData($d, 1, $long2, 2) Return DllStructGetData(DllStructCreate("uint64", DllStructGetPtr($d)),1) EndFunc Func _CoTaskMemFree($pMem) Local $aRes = DllCall("Ole32.dll", "none", "CoTaskMemFree", "ptr", $pMem) If @error Then SetError(1) EndFunc ;==>_CoTaskMemFree Func _ILCreateFromPath($sPath) Local $aRes = DllCall("shell32.dll", "ptr", "ILCreateFromPathW", "wstr", $sPath) If @error Then Return SetError(1, 0, 0) Return $aRes[0] EndFunc ;==>_ILCreateFromPath Func _SHCreateItemFromParsingName($szPath, $pbc, $riid, ByRef $pv) Local $aRes = DllCall("shell32.dll", "long", "SHCreateItemFromParsingName", "wstr", $szPath, "ptr", $pbc, "ptr", $riid, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[4] Return $aRes[0] EndFunc ;==>_SHCreateItemFromParsingName Func _SHBindToObject($psf, $pidl, $pbc, $riid, ByRef $pv) Local $aRes = DllCall("Shell32.dll", "long", "SHBindToObject", "ptr", $psf, "ptr", $pidl, "ptr", $pbc, "ptr", $riid, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[5] Return $aRes[0] EndFunc ;==>_SHBindToObject Func _SHBindToParent($pidl, $riid, ByRef $pv, ByRef $pidlLast) Local $aRes = DllCall("Shell32.dll", "long", "SHBindToParent", "ptr", $pidl, "ptr", $riid, "ptr*", 0, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[3] $pidlLast = $aRes[4] Return $aRes[0] EndFunc ;==>_SHBindToParent Func _StrRetToBuf($pSTRRET, $pidl, ByRef $sName, $iLength = 512) Local $aRes = DllCall("shlwapi.dll", "long", "StrRetToBufW", "ptr", $pSTRRET, "ptr", $pidl, "wstr", $sName, "uint", $iLength) If @error Then Return SetError(1, 0, 0) $sName = $aRes[3] Return $aRes[0] EndFunc ;==>_StrRetToBuf Exit Edit: Modified sp that $IImgFact.GetImage should work on x64, too. (look at ; <==== ) Edited December 19, 2010 by ProgAndy *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
trancexx Posted December 19, 2010 Share Posted December 19, 2010 Great ProgAndy. We should really implement structure-parameter. ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
KaFu Posted December 19, 2010 Author Share Posted December 19, 2010 Excellent , would've been a long and rough way for me ... lot's to study, thanks a lot! OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
ProgAndy Posted December 19, 2010 Share Posted December 19, 2010 Great ProgAndy. We should really implement structure-parameter.Yep, maybe we should begin with a simpler version, though. Somthing like "struct,64", DLLStructGetPtr($tStruct) and then copy the data from the struct in the parameter as a byte array with given length (here 64) *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
KaFu Posted December 20, 2010 Author Share Posted December 20, 2010 (edited) Whoooha , just fucking awesome how easy it was to integrate into SMF ...Andy, thanks again for this great piece of code ...(btw, you don't know by "accident" how to center the bitmaps if the ratio does not fit ?)Edit: Looking at the IShellItemImageFactory::GetImage Method setting the flag SIIGBF_BIGGERSIZEOK and resizing the returned bitmap myself seems to be the way to go... will check it out and post when done ... Edited December 20, 2010 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
ProgAndy Posted December 20, 2010 Share Posted December 20, 2010 This is an example including centering of the image and a cleaner calcualtion of the image portion to draw: expandcollapse popup#include<AutoItObject.au3> #include<WinAPI.au3> #include<WinAPIEx.au3> #include<WindowsConstants.au3> #include<Constants.au3> #include<GUIConstantsEx.au3> #include-once ;=============================================================================== #API "Extracting Image" ; IShellFolder ; IExtractImage ;=============================================================================== ;.......written by ProgAndy ;=============================================================================== #interface "IShellFolder" $sIID_IShellFolder = "{000214E6-0000-0000-C000-000000000046}" ; Definition Global Const $dtagIShellFolder = $dtagIUnknown & _ "ParseDisplayName hresult(hwnd;ptr;wstr;dword*;ptr*;dword*);" & _ "EnumObjects hresult(hwnd;dword;ptr*);" & _ "BindToObject hresult(ptr;ptr;ptr;ptr*);" & _ "BindToStorage hresult(ptr;ptr;ptr;ptr*);" & _ "CompareIDs hresult(lparam;ptr;ptr);" & _ "CreateViewObject hresult(hwnd;ptr;ptr*);" & _ "GetAttributesOf hresult(UINT;ptr;ulong*);" & _ "GetUIObjectOf hresult(hwnd;uint;ptr;ptr;uint*;ptr*);" & _ "GetDisplayNameOf hresult(ptr;uint;ptr);" & _ "SetNameOf hresult(hwnd;ptr;wstr;dword;ptr*);" ; List Global Const $ltagIShellFolder = $ltagIUnknown & _ "ParseDisplayName;" & _ "EnumObjects;" & _ "BindToObject;" & _ "BindToStorage;" & _ "CompareIDs;" & _ "CreateViewObject;" & _ "GetAttributesOf;" & _ "GetUIObjectOf;" & _ "GetDisplayNameOf;" & _ "SetNameOf;" ;=============================================================================== ;=============================================================================== #interface "IExtractImage" Global Const $sIID_IExtractImage = "{BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}" ; Definition Global Const $dtagIExtractImage = $dtagIUnknown & _ "GetLocation hresult(wstr;DWORD;DWORD*;ptr;dword;DWORD*);" & _ "Extract hresult(ptr*);" ; List Global Const $ltagIExtractImage = $ltagIUnknown & _ "GetLocation;" & _ "Extract;" ;=============================================================================== ;=============================================================================== #interface "IShellItemImageFactory" Global Const $sIID_IShellItemImageFactory = "{bcc18b79-ba16-442f-80c4-8a59c30c463b}" ; Definition Global Const $dtagIShellItemImageFactory = $dtagIUnknown & _ "GetImage hresult(uint64;dword;ptr*);" ; List Global Const $ltagIShellItemImageFactory = $ltagIUnknown & _ "GetImage;" ;=============================================================================== ;=============================================================================== #interface "IShellItem" Global Const $IID_IShellItem = "{43826d1e-e718-42ee-bc55-a1e261c37bfe}" Global Const $dtagIShellItem = $dtagIUnknown & _ "BindToHandler hresult(ptr;ptr;ptr;ptr*);" & _ "GetParent hresult(ptr*);" & _ "GetDisplayName hresult(dword;ptr*);" & _ "GetAttributes hresult(dword;dword*);" & _ "Compare hresult(ptr;dword;int*);" Global Const $ltagIShellItem = $ltagIUnknown & _ "BindToHandler;" & _ "GetParent;" & _ "GetDisplayName;" & _ "GetAttributes;" & _ "Compare;" ;=============================================================================== Global $hDCB, $hBmp _AutoItObject_StartUp() OnAutoItExitRegister("_close") Func _close() _WinAPI_DeleteDC($hDCB) _WinAPI_DeleteObject($hBmp) _AutoItObject_Shutdown() EndFunc ;==>_close $fUseAlphaBlend = False $sFileName = "D:\Eigene Bilder\Auto.png" If Not FileExists($sFileName) Then MsgBox(0, '', "Invalid File Name") Exit EndIf $tIIDImgFact = _AutoItObject_CLSIDFromString($sIID_IShellItemImageFactory) Dim $pImgFact If 0 = _SHCreateItemFromParsingName($sFileName, 0, DllStructGetPtr($tIIDImgFact), $pImgFact) And $pImgFact Then $IImgFact = _AutoItObject_WrapperCreate($pImgFact, $dtagIShellItemImageFactory) $r = $IImgFact.GetImage(_MakeUINT64(128, 128), 0, 0) $hBmp = $r[3] Else $pidl = _WinAPI_ShellILCreateFromPath($sFileName) Dim $pIShellFolder, $pRelative $tRIID = _AutoItObject_CLSIDFromString($sIID_IShellFolder) $tRIIDExtract = _AutoItObject_CLSIDFromString($sIID_IExtractImage) If StringInStr(FileGetAttrib($sFileName), "D", 1) Then MsgBox(0, '', "Cannot create preview for Folders on Windows prior to Vista") Exit Else _SHBindToParent($pidl, DllStructGetPtr($tRIID), $pIShellFolder, $pRelative) $IShellFolder = _AutoItObject_WrapperCreate($pIShellFolder, $dtagIShellFolder) $tSTRRET = DllStructCreate("uint uType;ptr data;") $r = $IShellFolder.GetDisplayNameOf(Number($pRelative), 0, Number(DllStructGetPtr($tSTRRET))) Dim $name _StrRetToBuf(DllStructGetPtr($tSTRRET), 0, $name, 512) $tSTRRET = 0 MsgBox(0, 'name of item', $name) $tArray = DllStructCreate("ptr") DllStructSetData($tArray, 1, $pRelative) $r = $IShellFolder.GetUIObjectOf(0, 1, Number(DllStructGetPtr($tArray)), Number(DllStructGetPtr($tRIIDExtract)), 0, 0) $IExtractImage = _AutoItObject_WrapperCreate($r[6], $dtagIExtractImage) EndIf $tSize = DllStructCreate("long;long") DllStructSetData($tSize, 1, 128) DllStructSetData($tSize, 2, 128) $r = $IExtractImage.GetLocation("", 1024, 0, Number(DllStructGetPtr($tSize)), 32, 0) MsgBox(0, '', $r[1]) $r = $IExtractImage.Extract(0) $hBmp = $r[1] $IShellFolder = 0 _WinAPI_CoTaskMemFree($pidl) EndIf $tBMP = DllStructCreate($tagBITMAP) Global $bmWidth = 128, $bmHeight = 128 If _WinAPI_GetObject($hBmp, DllStructGetSize($tBMP), DllStructGetPtr($tBMP)) Then _ Global $bmWidth = DllStructGetData($tBMP, "bmWidth"), $bmHeight = Abs(DllStructGetData($tBMP, "bmHeight")) $hGUI = GUICreate("test", 256, 128) GUIRegisterMsg($WM_PAINT, "_WM_PAINT") $btnColor = GUICtrlCreateButton("ColorChange", 130, 20, 100, 20) $hDC = _WinAPI_GetDC(0) $hDCB = _WinAPI_CreateCompatibleDC($hDC) _WinAPI_SelectObject($hDCB, $hBmp) _WinAPI_ReleaseDC(0, $hDC) $IExtractImage = 0 GUISetState() While 1 Switch GUIGetMsg() Case -3 ExitLoop Case $btnColor GUISetBkColor(Random(0, 0xFFFFFF, 1)) EndSwitch WEnd Func _WM_PAINT($hWnd, $uMsg, $wParam, $lParam) Local $tPS Local $hDC = _WinAPI_BeginPaint($hWnd, $tPS) Local $x = DllStructGetData($tPS, "rPaint", 1) Local $y = DllStructGetData($tPS, "rPaint", 2) Local $x2 = DllStructGetData($tPS, "rPaint", 3) Local $y2 = DllStructGetData($tPS, "rPaint", 4) If $x <= 128 And $x2 >= 0 And $y <= 128 And $y2 >= 0 Then If $x2 > 128 Then $x2 = 128 If $x < 0 Then $x = 0 If $y < 0 Then $y = 0 If $y2 > 128 Then $y2 = 128 Local $ImgX = $x-0, $ImgY = $y-0 If $bmWidth < 127 Then $x += Int((128-$bmWidth)/2) If $bmHeight < 127 Then $y += Int((128-$bmHeight)/2) Local $ImgW = $x2-$x, $ImgH = $y2-$y If $ImgW > $bmWidth Then $ImgW = $bmWidth If $ImgH > $bmHeight Then $ImgH = $bmHeight If $x < $x2 And $y < $y2 Then If $fUseAlphaBlend Then _WinAPI_AlphaBlend($hDC, $x, $y, $ImgW, $ImgH, $hDCB, $ImgX, $ImgY, $ImgW, $ImgH, 255, True) Else _WinAPI_BitBlt($hDC, $x, $y, $ImgW, $ImgH, $hDCB, $ImgX, $ImgY, $SRCCOPY) EndIf EndIf EndIf _WinAPI_EndPaint($hWnd, $tPS) Return $GUI_RUNDEFMSG EndFunc ;==>_WM_PAINT Func _MakeUINT64($long1, $long2) Local $d = DllStructCreate("align 4;dword[2]") DllStructSetData($d, 1, $long1, 1) DllStructSetData($d, 1, $long2, 2) Return DllStructGetData(DllStructCreate("uint64", DllStructGetPtr($d)),1) EndFunc Func _SHCreateItemFromParsingName($szPath, $pbc, $riid, ByRef $pv) Local $aRes = DllCall("shell32.dll", "long", "SHCreateItemFromParsingName", "wstr", $szPath, "ptr", $pbc, "ptr", $riid, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[4] Return $aRes[0] EndFunc ;==>_SHCreateItemFromParsingName Func _SHBindToObject($psf, $pidl, $pbc, $riid, ByRef $pv) Local $aRes = DllCall("Shell32.dll", "long", "SHBindToObject", "ptr", $psf, "ptr", $pidl, "ptr", $pbc, "ptr", $riid, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[5] Return $aRes[0] EndFunc ;==>_SHBindToObject Func _SHBindToParent($pidl, $riid, ByRef $pv, ByRef $pidlLast) Local $aRes = DllCall("Shell32.dll", "long", "SHBindToParent", "ptr", $pidl, "ptr", $riid, "ptr*", 0, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[3] $pidlLast = $aRes[4] Return $aRes[0] EndFunc ;==>_SHBindToParent Func _StrRetToBuf($pSTRRET, $pidl, ByRef $sName, $iLength = 512) Local $aRes = DllCall("shlwapi.dll", "long", "StrRetToBufW", "ptr", $pSTRRET, "ptr", $pidl, "wstr", $sName, "uint", $iLength) If @error Then Return SetError(1, 0, 0) $sName = $aRes[3] Return $aRes[0] EndFunc ;==>_StrRetToBuf *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
Yashied Posted December 20, 2010 Share Posted December 20, 2010 (edited) KaFu, why do not use GDI+? Or you need a thumbnails not only for images? Edited December 20, 2010 by Yashied My UDFs: iKey | FTP Uploader | Battery Checker | Boot Manager | Font Viewer | UDF Keyword Manager | Run Dialog Replacement | USBProtect | 3D Axis | Calculator | Sleep | iSwitcher | TM | NetHelper | File Types Manager | Control Viewer | SynFolders | DLL Helper Animated Tray Icons UDF Library | Hotkeys UDF Library | Hotkeys Input Control UDF Library | Caret Shape UDF Library | Context Help UDF Library | Most Recently Used List UDF Library | Icons UDF Library | FTP UDF Library | Script Communications UDF Library | Color Chooser UDF Library | Color Picker Control UDF Library | IPHelper (Vista/7) UDF Library | WinAPI Extended UDF Library | WinAPIVhd UDF Library | Icon Chooser UDF Library | Copy UDF Library | Restart UDF Library | Event Log UDF Library | NotifyBox UDF Library | Pop-up Windows UDF Library | TVExplorer UDF Library | GuiHotKey UDF Library | GuiSysLink UDF Library | Package UDF Library | Skin UDF Library | AITray UDF Library | RDC UDF Library Appropriate path | Button text color | Gaussian random numbers | Header's styles (Vista/7) | ICON resource enumeration | Menu & INI | Tabbed string size | Tab's skin | Pop-up circular menu | Progress Bar without animation (Vista/7) | Registry export | Registry path jumping | Unique hardware ID | Windows alignment More... Link to comment Share on other sites More sharing options...
KaFu Posted December 20, 2010 Author Share Posted December 20, 2010 (edited) KaFu, why do not use GDI+? Or you need a thumbnails not only for images? Hi Yashied, yep, I want the have a thumbnail for every file, GDIs not enough (but part of the solution). Andy, thanks for the heads up. Currently I'm working out the IShellItemImageFactory part for Win7. I want to add the bitmaps to an Imagelist to use with the Listview. Now I found this passage on google: "Another thing to watch out for is that the API sometimes returns bitmaps that use pre-multiplied alpha and sometimes ones that use normal alpha, with no proper way (except heuristics, which can go wrong) to tell which. It's a pretty poor API. – Leo Davidson Dec 13 at 20:12" Resizing already works quite good, but there indeed seem to be problems with certain Alpha values (background black for .png and .ico files). Edit: Added jpg example (works fine too). expandcollapse popup; http://www.autoitscript.com/forum/topic/123365-autoitobject-suitable-to-retrieve-iextractimage-interface-pointer-from-shellfolder/page__view__findpost__p__856882 ; ProgAndy #cs Another thing to watch out for is that the API sometimes returns bitmaps that use pre-multiplied alpha and sometimes ones that use normal alpha, with no proper way (except heuristics, which can go wrong) to tell which. It's a pretty poor API. :( – Leo Davidson Dec 13 at 20:12 #ce #include <WindowsConstants.au3> #include <Constants.au3> #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <GuiListView.au3> #include <GuiImageList.au3> #include<AutoItObject.au3> #include<WinAPIEx.au3> #include-once ;=============================================================================== #API "Extracting Image" ; IShellFolder ; IExtractImage ;=============================================================================== ;.......written by ProgAndy ;=============================================================================== #interface "IShellFolder" $sIID_IShellFolder = "{000214E6-0000-0000-C000-000000000046}" ; Definition Global Const $dtagIShellFolder = $dtagIUnknown & _ "ParseDisplayName hresult(hwnd;ptr;wstr;dword*;ptr*;dword*);" & _ "EnumObjects hresult(hwnd;dword;ptr*);" & _ "BindToObject hresult(ptr;ptr;ptr;ptr*);" & _ "BindToStorage hresult(ptr;ptr;ptr;ptr*);" & _ "CompareIDs hresult(lparam;ptr;ptr);" & _ "CreateViewObject hresult(hwnd;ptr;ptr*);" & _ "GetAttributesOf hresult(UINT;ptr;ulong*);" & _ "GetUIObjectOf hresult(hwnd;uint;ptr;ptr;uint*;ptr*);" & _ "GetDisplayNameOf hresult(ptr;uint;ptr);" & _ "SetNameOf hresult(hwnd;ptr;wstr;dword;ptr*);" ; List Global Const $ltagIShellFolder = $ltagIUnknown & _ "ParseDisplayName;" & _ "EnumObjects;" & _ "BindToObject;" & _ "BindToStorage;" & _ "CompareIDs;" & _ "CreateViewObject;" & _ "GetAttributesOf;" & _ "GetUIObjectOf;" & _ "GetDisplayNameOf;" & _ "SetNameOf;" ;=============================================================================== ;=============================================================================== #interface "IExtractImage" Global Const $sIID_IExtractImage = "{BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}" ; Definition Global Const $dtagIExtractImage = $dtagIUnknown & _ "GetLocation hresult(wstr;DWORD;DWORD*;ptr;dword;DWORD*);" & _ "Extract hresult(ptr*);" ; List Global Const $ltagIExtractImage = $ltagIUnknown & _ "GetLocation;" & _ "Extract;" ;=============================================================================== ;=============================================================================== #interface "IShellItemImageFactory" Global Const $sIID_IShellItemImageFactory = "{bcc18b79-ba16-442f-80c4-8a59c30c463b}" ; Definition Global Const $dtagIShellItemImageFactory = $dtagIUnknown & _ "GetImage hresult(uint64;dword;ptr*);" ; <==== uint64 instead of long;long ; List Global Const $ltagIShellItemImageFactory = $ltagIUnknown & _ "GetImage;" ;=============================================================================== ;=============================================================================== #interface "IShellItem" Global Const $IID_IShellItem = "{43826d1e-e718-42ee-bc55-a1e261c37bfe}" Global Const $dtagIShellItem = $dtagIUnknown & _ "BindToHandler hresult(ptr;ptr;ptr;ptr*);" & _ "GetParent hresult(ptr*);" & _ "GetDisplayName hresult(dword;ptr*);" & _ "GetAttributes hresult(dword;dword*);" & _ "Compare hresult(ptr;dword;int*);" Global Const $ltagIShellItem = $ltagIUnknown & _ "BindToHandler;" & _ "GetParent;" & _ "GetDisplayName;" & _ "GetAttributes;" & _ "Compare;" ;=============================================================================== _AutoItObject_StartUp() Global $h_IShellFolder_Bmp Global $h_IShellFolder_DCB Global $f_IShellFolder_UseAlphaBlend = False Global $i_IShellFolder_Preview_Size = 128 OnAutoItExitRegister("_IShellFolder_Exit") _GDIPlus_Startup() $tIIDImgFact = _AutoItObject_CLSIDFromString($sIID_IShellItemImageFactory) $sBaseDir = StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", 0, -1)) $sFileName1 = $sBaseDir & "Examples\GUI" $sFileName2 = $sFileName1 & "\Advanced\Images\Blue.bmp" $sFileName3 = $sFileName1 & "\merlin.gif" $sFileName4 = $sFileName1 & "\Torus.png" $sFileName5 = $sBaseDir & "icons\au3.ico" $sFileName6 = $sFileName1 & "\mslogo.jpg" #region LV-Example GUICreate("ListView Set Image List", 500, 800) $hListView = GUICtrlCreateListView("", 2, 2, 496, 796) GUISetState() ; Load images $hImage = _GUIImageList_Create($i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size, 5, 3, 1) _GUIImageList_Add($hImage, _IShellFolder_Extract_hBMP($sFileName1)) _GUIImageList_Add($hImage, _IShellFolder_Extract_hBMP($sFileName2)) _GUIImageList_Add($hImage, _IShellFolder_Extract_hBMP($sFileName3)) _GUIImageList_Add($hImage, _IShellFolder_Extract_hBMP($sFileName4)) _GUIImageList_Add($hImage, _IShellFolder_Extract_hBMP($sFileName5)) _GUIImageList_Add($hImage, _IShellFolder_Extract_hBMP($sFileName6)) _GUICtrlListView_SetImageList($hListView, $hImage, 1) ; Add columns _GUICtrlListView_AddColumn($hListView, "Filename", 400) ; Add items _GUICtrlListView_AddItem($hListView, $sFileName1, 0) _GUICtrlListView_AddItem($hListView, $sFileName2, 1) _GUICtrlListView_AddItem($hListView, $sFileName3, 2) _GUICtrlListView_AddItem($hListView, $sFileName4, 3) _GUICtrlListView_AddItem($hListView, $sFileName5, 4) _GUICtrlListView_AddItem($hListView, $sFileName6, 5) ; Loop until user exits Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete() #endregion LV-Example Func _IShellFolder_Exit() _GDIPlus_Shutdown () _WinAPI_DeleteObject($h_IShellFolder_Bmp) _AutoItObject_Shutdown() EndFunc ;==>_IShellFolder_Exit Func _IShellFolder_Extract_hBMP($sFileName) If Not FileExists($sFileName) Then Return SetError(1) If IsHWnd($h_IShellFolder_Bmp) Then _WinAPI_DeleteObject($h_IShellFolder_Bmp) Dim $pImgFact If 0 = _IShellFolder_SHCreateItemFromParsingName($sFileName, 0, DllStructGetPtr($tIIDImgFact), $pImgFact) And $pImgFact Then $IImgFact = _AutoItObject_WrapperCreate($pImgFact, $dtagIShellItemImageFactory) $r = $IImgFact.GetImage(_IShellFolder_MakeUINT64($i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size), 8, 0) ; <==== _IShellFolder_MakeUINT64 added ConsoleWrite($sFileName & @tab & $r[3] & @crlf) If $r[3] = 0 Or StringInStr(FileGetAttrib($sFileName), "D") Then ; no thumbnail available OR target is folder $r = $IImgFact.GetImage(_IShellFolder_MakeUINT64($i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size), 0, 0) ; <==== _IShellFolder_MakeUINT64 added $h_IShellFolder_Bmp = $r[3] Else $r = $IImgFact.GetImage(_IShellFolder_MakeUINT64($i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size), 1, 0) ; <==== _IShellFolder_MakeUINT64 added $h_IShellFolder_Bmp = _IShellFolder_GetImage($r[3], $i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size) EndIf ;EndIf Else $pidl = _IShellFolder_ILCreateFromPath($sFileName) Dim $pIShellFolder, $pRelative $tRIID = _AutoItObject_CLSIDFromString($sIID_IShellFolder) $tRIIDExtract = _AutoItObject_CLSIDFromString($sIID_IExtractImage) If StringInStr(FileGetAttrib($sFileName), "D", 1) Then Return 1 ;MsgBox(0, '', "Cannot create preview for Folders on Windows prior to Vista") ;Exit Else _SHBindToParent($pidl, DllStructGetPtr($tRIID), $pIShellFolder, $pRelative) $IShellFolder = _AutoItObject_WrapperCreate($pIShellFolder, $dtagIShellFolder) $tSTRRET = DllStructCreate("uint uType;ptr data;") $r = $IShellFolder.GetDisplayNameOf(Number($pRelative), 0, Number(DllStructGetPtr($tSTRRET))) Dim $name _IShellFolder_StrRetToBuf(DllStructGetPtr($tSTRRET), 0, $name, 512) $tSTRRET = 0 ;MsgBox(0, 'name of item', $name) $tArray = DllStructCreate("ptr") DllStructSetData($tArray, 1, $pRelative) $r = $IShellFolder.GetUIObjectOf(0, 1, Number(DllStructGetPtr($tArray)), Number(DllStructGetPtr($tRIIDExtract)), 0, 0) $IExtractImage = _AutoItObject_WrapperCreate($r[6], $dtagIExtractImage) EndIf $tSize = DllStructCreate("long;long") DllStructSetData($tSize, 1, $i_IShellFolder_Preview_Size) DllStructSetData($tSize, 2, $i_IShellFolder_Preview_Size) $r = $IExtractImage.GetLocation("", 1024, 0, Number(DllStructGetPtr($tSize)), 32, 0) ;MsgBox(0, '', $r[1]) $r = $IExtractImage.Extract(0) $h_IShellFolder_Bmp = $r[1] $IShellFolder = 0 _IShellFolder_CoTaskMemFree($pidl) EndIf $IExtractImage = 0 Return $h_IShellFolder_Bmp EndFunc ;==>_IShellFolder_Extract_hBMP Func _IShellFolder_GetImage($hBmp_Source, $i_TargetWidth = 32, $i_TargetHeight = 32) Local $hBmp1, $hBitmap, $hGraphic, $hImage, $iW, $iH, $aGS, $hBmp2 $hBmp1 = _WinAPI_CreateBitmap($i_TargetWidth, $i_TargetHeight, 1, 32) $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBmp1) $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBitmap) _WinAPI_DeleteObject($hBmp1) _GDIPlus_GraphicsClear($hGraphic, 0xFFFFFFFF) $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBmp_Source) $iW = _GDIPlus_ImageGetWidth($hImage) $iH = _GDIPlus_ImageGetHeight($hImage) $aGS = _IShellFolder_GetScale($iW, $iH, $i_TargetWidth) _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage, $aGS[0], $aGS[1], $aGS[2], $aGS[3]) _GDIPlus_ImageDispose($hImage) _GDIPlus_GraphicsDispose($hGraphic) $hBmp2 = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) _GDIPlus_BitmapDispose($hBitmap) Return $hBmp2 EndFunc ;==>_IShellFolder_GetImage Func _IShellFolder_GetScale($iW, $iH, $i_TargetWidth) Local $aRet[4] If $iW <= $i_TargetWidth And $iH <= $i_TargetWidth Then $aRet[2] = $iW $aRet[3] = $iH $aRet[0] = ($i_TargetWidth - $aRet[2]) / 2 $aRet[1] = ($i_TargetWidth - $aRet[3]) / 2 ElseIf $iW > $iH Then $aRet[2] = $i_TargetWidth $aRet[3] = $iH / ($iW / $i_TargetWidth) $aRet[0] = 0 $aRet[1] = ($i_TargetWidth - $aRet[3]) / 2 ElseIf $iW < $iH Then $aRet[2] = $iW / ($iH / $i_TargetWidth) $aRet[3] = $i_TargetWidth $aRet[0] = ($i_TargetWidth - $aRet[2]) / 2 $aRet[1] = 0 ElseIf $iW = $iH Then $aRet[2] = $i_TargetWidth $aRet[3] = $i_TargetWidth $aRet[0] = 0 $aRet[1] = 0 EndIf Return $aRet EndFunc ;==>_IShellFolder_GetScale #cs Func _WM_PAINT($hWnd, $uMsg, $wParam, $lParam) Local $tPS Local $hDC = _WinAPI_BeginPaint($hWnd, $tPS) $x = DllStructGetData($tPS, "rPaint", 1) $y = DllStructGetData($tPS, "rPaint", 2) $w = DllStructGetData($tPS, "rPaint", 3) - $x $h = DllStructGetData($tPS, "rPaint", 4) - $y If $x <= 128 Then If $x + $w > 128 Then $w = 128 - $x If $f_IShellFolder_UseAlphaBlend Then _WinAPI_AlphaBlend($hDC, $x, $y, $w, $h, $h_IShellFolder_DCB, $x, $y, $w, $h, 255, True) Else _WinAPI_BitBlt($hDC, $x, $y, $w, $h, $h_IShellFolder_DCB, $x, $y, $SRCCOPY) EndIf EndIf _WinAPI_EndPaint($hWnd, $tPS) Return $GUI_RUNDEFMSG EndFunc ;==>_WM_PAINT #ce Func _IShellFolder_MakeUINT64($long1, $long2) Local $d = DllStructCreate("align 4;dword[2]") DllStructSetData($d, 1, $long1, 1) DllStructSetData($d, 1, $long2, 2) Return DllStructGetData(DllStructCreate("uint64", DllStructGetPtr($d)), 1) EndFunc ;==>_IShellFolder_MakeUINT64 Func _IShellFolder_CoTaskMemFree($pMem) Local $aRes = DllCall("Ole32.dll", "none", "CoTaskMemFree", "ptr", $pMem) If @error Then SetError(1) EndFunc ;==>_IShellFolder_CoTaskMemFree Func _IShellFolder_ILCreateFromPath($sPath) Local $aRes = DllCall("shell32.dll", "ptr", "ILCreateFromPathW", "wstr", $sPath) If @error Then Return SetError(1, 0, 0) Return $aRes[0] EndFunc ;==>_IShellFolder_ILCreateFromPath Func _IShellFolder_SHCreateItemFromParsingName($szPath, $pbc, $riid, ByRef $pv) Local $aRes = DllCall("shell32.dll", "long", "SHCreateItemFromParsingName", "wstr", $szPath, "ptr", $pbc, "ptr", $riid, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[4] Return $aRes[0] EndFunc ;==>_IShellFolder_SHCreateItemFromParsingName Func _IShellFolder_SHBindToObject($psf, $pidl, $pbc, $riid, ByRef $pv) Local $aRes = DllCall("Shell32.dll", "long", "SHBindToObject", "ptr", $psf, "ptr", $pidl, "ptr", $pbc, "ptr", $riid, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[5] Return $aRes[0] EndFunc ;==>_IShellFolder_SHBindToObject Func _SHBindToParent($pidl, $riid, ByRef $pv, ByRef $pidlLast) Local $aRes = DllCall("Shell32.dll", "long", "SHBindToParent", "ptr", $pidl, "ptr", $riid, "ptr*", 0, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[3] $pidlLast = $aRes[4] Return $aRes[0] EndFunc ;==>_SHBindToParent Func _IShellFolder_StrRetToBuf($pSTRRET, $pidl, ByRef $sName, $iLength = 512) Local $aRes = DllCall("shlwapi.dll", "long", "StrRetToBufW", "ptr", $pSTRRET, "ptr", $pidl, "wstr", $sName, "uint", $iLength) If @error Then Return SetError(1, 0, 0) $sName = $aRes[3] Return $aRes[0] EndFunc ;==>_IShellFolder_StrRetToBuf Edited December 20, 2010 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
KaFu Posted December 20, 2010 Author Share Posted December 20, 2010 (edited) Sooo, after playing around with IExtractImage (used for XP) I came up with an update example. On XP it will show the same GUI two times. On Vista+ the first example is created with the IShellItemImageFactory interface and the second with the IExtractImage interface. I added replacements of the thumbnails in IExtractImage with the corresponding icons, if the thumbnail could not be created (Directories, other files without a preview (e.g. the .chm file)). Overall it already looks really good, but there's an alpha (? - default background color, should be white) problem in IShellItemImageFactory and IExtractImage too (or I'm messing up at some point and do not realize it ). expandcollapse popup#region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_UseX64=n #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** ; http://www.autoitscript.com/forum/topic/123365-autoitobject-suitable-to-retrieve-iextractimage-interface-pointer-from-shellfolder/page__view__findpost__p__856882 ; ProgAndy #cs Another thing to watch out for is that the API sometimes returns bitmaps that use pre-multiplied alpha and sometimes ones that use normal alpha, with no proper way (except heuristics, which can go wrong) to tell which. It's a pretty poor API. :( – Leo Davidson Dec 13 at 20:12 #ce #include <WindowsConstants.au3> #include <Constants.au3> #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <GuiListView.au3> #include <GuiImageList.au3> #include<AutoItObject.au3> #include<WinAPIEx.au3> #include-once ;=============================================================================== #API "Extracting Image" ; IShellFolder ; IExtractImage ;=============================================================================== ;.......written by ProgAndy ;=============================================================================== #interface "IShellFolder" $sIID_IShellFolder = "{000214E6-0000-0000-C000-000000000046}" ; Definition Global Const $dtagIShellFolder = $dtagIUnknown & _ "ParseDisplayName hresult(hwnd;ptr;wstr;dword*;ptr*;dword*);" & _ "EnumObjects hresult(hwnd;dword;ptr*);" & _ "BindToObject hresult(ptr;ptr;ptr;ptr*);" & _ "BindToStorage hresult(ptr;ptr;ptr;ptr*);" & _ "CompareIDs hresult(lparam;ptr;ptr);" & _ "CreateViewObject hresult(hwnd;ptr;ptr*);" & _ "GetAttributesOf hresult(UINT;ptr;ulong*);" & _ "GetUIObjectOf hresult(hwnd;uint;ptr;ptr;uint*;ptr*);" & _ "GetDisplayNameOf hresult(ptr;uint;ptr);" & _ "SetNameOf hresult(hwnd;ptr;wstr;dword;ptr*);" ; List Global Const $ltagIShellFolder = $ltagIUnknown & _ "ParseDisplayName;" & _ "EnumObjects;" & _ "BindToObject;" & _ "BindToStorage;" & _ "CompareIDs;" & _ "CreateViewObject;" & _ "GetAttributesOf;" & _ "GetUIObjectOf;" & _ "GetDisplayNameOf;" & _ "SetNameOf;" ;=============================================================================== ;=============================================================================== #interface "IExtractImage" Global Const $sIID_IExtractImage = "{BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}" ; Definition Global Const $dtagIExtractImage = $dtagIUnknown & _ "GetLocation hresult(wstr;DWORD;DWORD*;ptr;dword;DWORD*);" & _ "Extract hresult(ptr*);" ; List Global Const $ltagIExtractImage = $ltagIUnknown & _ "GetLocation;" & _ "Extract;" ;=============================================================================== ;=============================================================================== #interface "IShellItemImageFactory" Global Const $sIID_IShellItemImageFactory = "{bcc18b79-ba16-442f-80c4-8a59c30c463b}" ; Definition Global Const $dtagIShellItemImageFactory = $dtagIUnknown & _ "GetImage hresult(uint64;dword;ptr*);" ; <==== uint64 instead of long;long ; List Global Const $ltagIShellItemImageFactory = $ltagIUnknown & _ "GetImage;" ;=============================================================================== ;=============================================================================== #interface "IShellItem" Global Const $IID_IShellItem = "{43826d1e-e718-42ee-bc55-a1e261c37bfe}" Global Const $dtagIShellItem = $dtagIUnknown & _ "BindToHandler hresult(ptr;ptr;ptr;ptr*);" & _ "GetParent hresult(ptr*);" & _ "GetDisplayName hresult(dword;ptr*);" & _ "GetAttributes hresult(dword;dword*);" & _ "Compare hresult(ptr;dword;int*);" Global Const $ltagIShellItem = $ltagIUnknown & _ "BindToHandler;" & _ "GetParent;" & _ "GetDisplayName;" & _ "GetAttributes;" & _ "Compare;" ;=============================================================================== _AutoItObject_StartUp() Global $h_IShellFolder_Bmp Global $h_IShellFolder_DCB Global $b_IExtractImage_Force = False ; default is to use IShellItemImageFactory if available (Vista+) or IExtractImage on older system (XP), set to true to force IExtractImage usage on Vista+ Global $i_IShellFolder_Preview_Size = 48 OnAutoItExitRegister("_IShellFolder_Exit") _GDIPlus_Startup() $tIIDImgFact = _AutoItObject_CLSIDFromString($sIID_IShellItemImageFactory) _LV_Example() $b_IExtractImage_Force = True _LV_Example() Func _LV_Example() $sBaseDir = StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", 0, -1)) $sFileName1 = $sBaseDir & "Examples\GUI" $sFileName2 = $sFileName1 & "\Advanced\Images\Blue.bmp" $sFileName3 = $sFileName1 & "\merlin.gif" $sFileName4 = $sFileName1 & "\Torus.png" $sFileName5 = $sBaseDir & "icons\au3.ico" $sFileName6 = $sFileName1 & "\mslogo.jpg" $sFileName7 = $sBaseDir & "AutoIt.chm" #region LV-Example Switch $b_IExtractImage_Force Case True GUICreate("ListView Example - IExtractImage Interface", 500, 800) Case Else GUICreate("ListView Example - IShellItemImageFactory Interface", 500, 800) EndSwitch $hListView = GUICtrlCreateListView("", 2, 2, 496, 796) GUISetState() ; Load images $hImage = _GUIImageList_Create($i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size, 5, 3, 1) _IShellFolder_GUIImageList_Add($hImage, $sFileName1) _IShellFolder_GUIImageList_Add($hImage, $sFileName2) _IShellFolder_GUIImageList_Add($hImage, $sFileName3) _IShellFolder_GUIImageList_Add($hImage, $sFileName4) _IShellFolder_GUIImageList_Add($hImage, $sFileName5) _IShellFolder_GUIImageList_Add($hImage, $sFileName6) _IShellFolder_GUIImageList_Add($hImage, $sFileName7) _GUICtrlListView_SetImageList($hListView, $hImage, 1) ; Add columns _GUICtrlListView_AddColumn($hListView, "Filename", 400) ; Add items _GUICtrlListView_AddItem($hListView, $sFileName1, 0) _GUICtrlListView_AddItem($hListView, $sFileName2, 1) _GUICtrlListView_AddItem($hListView, $sFileName3, 2) _GUICtrlListView_AddItem($hListView, $sFileName4, 3) _GUICtrlListView_AddItem($hListView, $sFileName5, 4) _GUICtrlListView_AddItem($hListView, $sFileName6, 5) _GUICtrlListView_AddItem($hListView, $sFileName7, 6) ; Loop until user exits Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete() #endregion LV-Example EndFunc ;==>_LV_Example Func _IShellFolder_Exit() _GDIPlus_Shutdown() _WinAPI_DeleteObject($h_IShellFolder_Bmp) _AutoItObject_Shutdown() EndFunc ;==>_IShellFolder_Exit Func _IShellFolder_GUIImageList_Add($hIML, $sFilename) $hBMP = _IShellFolder_Extract_hBMP($sFilename) Switch $hBMP Case 1 ; Folder under XP If $i_IShellFolder_Preview_Size >= 48 Then _GUIImageList_AddIcon($hIML, @SystemDir & "\shell32.dll", 3, True) Else _GUIImageList_AddIcon($hIML, @SystemDir & "\shell32.dll", 3, False) EndIf Case 2 ; If $i_IShellFolder_Preview_Size >= 48 Then $hIcon = _WinAPI_ShellExtractAssociatedIcon($sFilename, 0) _GUIImageList_ReplaceIcon($hIML, -1, $hIcon) _WinAPI_DestroyIcon($hIcon) Else $hIcon = _WinAPI_ShellExtractAssociatedIcon($sFilename, 1) _GUIImageList_ReplaceIcon($hIML, -1, $hIcon) _WinAPI_DestroyIcon($hIcon) EndIf Case Else _GUIImageList_Add($hIML, $hBMP) EndSwitch EndFunc ;==>_IShellFolder_GUIImageList_Add Func _IShellFolder_Extract_hBMP($sFilename) If Not FileExists($sFilename) Then Return SetError(1) If IsHWnd($h_IShellFolder_Bmp) Then _WinAPI_DeleteObject($h_IShellFolder_Bmp) Dim $pImgFact If 0 = _IShellFolder_SHCreateItemFromParsingName($sFilename, 0, DllStructGetPtr($tIIDImgFact), $pImgFact) And $pImgFact And Not $b_IExtractImage_Force Then $IImgFact = _AutoItObject_WrapperCreate($pImgFact, $dtagIShellItemImageFactory) $r = $IImgFact.GetImage(_IShellFolder_MakeUINT64($i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size), 8, 0) ; <==== _IShellFolder_MakeUINT64 added ;ConsoleWrite($sFileName & @TAB & $r[3] & @CRLF) If $r[3] = 0 Or StringInStr(FileGetAttrib($sFilename), "D") Then ; no thumbnail available OR target is folder $r = $IImgFact.GetImage(_IShellFolder_MakeUINT64($i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size), 0, 0) ; <==== _IShellFolder_MakeUINT64 added $h_IShellFolder_Bmp = $r[3] Else $r = $IImgFact.GetImage(_IShellFolder_MakeUINT64($i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size), 1, 0) ; <==== _IShellFolder_MakeUINT64 added $h_IShellFolder_Bmp = _IShellFolder_GetImage($r[3], $i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size) EndIf ;EndIf Else $pidl = _IShellFolder_ILCreateFromPath($sFilename) Dim $pIShellFolder, $pRelative $tRIID = _AutoItObject_CLSIDFromString($sIID_IShellFolder) $tRIIDExtract = _AutoItObject_CLSIDFromString($sIID_IExtractImage) ;ConsoleWrite($pidl & @crlf) If StringInStr(FileGetAttrib($sFilename), "D", 1) Then _IShellFolder_CoTaskMemFree($pidl) Return 1 ;MsgBox(0, '', "Cannot create preview for Folders on Windows prior to Vista") ;Exit Else _SHBindToParent($pidl, DllStructGetPtr($tRIID), $pIShellFolder, $pRelative) $IShellFolder = _AutoItObject_WrapperCreate($pIShellFolder, $dtagIShellFolder) ;ConsoleWrite(IsObj($IShellFolder) & @crlf) $tSTRRET = DllStructCreate("uint uType;ptr data;") $r = $IShellFolder.GetDisplayNameOf(Number($pRelative), 0, Number(DllStructGetPtr($tSTRRET))) Dim $name _IShellFolder_StrRetToBuf(DllStructGetPtr($tSTRRET), 0, $name, 512) $tSTRRET = 0 ;MsgBox(0, 'name of item', $name) $tArray = DllStructCreate("ptr") DllStructSetData($tArray, 1, $pRelative) $r = $IShellFolder.GetUIObjectOf(0, 1, Number(DllStructGetPtr($tArray)), Number(DllStructGetPtr($tRIIDExtract)), 0, 0) $IExtractImage = _AutoItObject_WrapperCreate($r[6], $dtagIExtractImage) EndIf If Not IsObj($IExtractImage) Then Return 2 Else $tSize = DllStructCreate("long;long") DllStructSetData($tSize, 1, $i_IShellFolder_Preview_Size) DllStructSetData($tSize, 2, $i_IShellFolder_Preview_Size) $r = $IExtractImage.GetLocation("", 1024, 0, Number(DllStructGetPtr($tSize)), 32, 0x0020 + 0x0200) ;IEIFLAG_SCREEN + IEIFLAG_QUALITY ;MsgBox(0, '', $r[1]) $r = $IExtractImage.Extract(0) $h_IShellFolder_Bmp = $r[1] ; ConsoleWrite($name & @TAB & $h_IShellFolder_Bmp & @CRLF) $IShellFolder = 0 _IShellFolder_CoTaskMemFree($pidl) $h_IShellFolder_Bmp2 = _IShellFolder_GetImage($h_IShellFolder_Bmp, $i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size) _WinAPI_DeleteObject($h_IShellFolder_Bmp) $h_IShellFolder_Bmp = $h_IShellFolder_Bmp2 EndIf EndIf $IExtractImage = 0 Return $h_IShellFolder_Bmp EndFunc ;==>_IShellFolder_Extract_hBMP Func _IShellFolder_GetImage($hBmp_Source, $i_TargetWidth = 32, $i_TargetHeight = 32) Local $hBmp1, $hBitmap, $hGraphic, $hImage, $iW, $iH, $aGS, $hBmp2 $hBmp1 = _WinAPI_CreateBitmap($i_TargetWidth, $i_TargetHeight, 1, 32) $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBmp1) $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBitmap) _WinAPI_DeleteObject($hBmp1) _GDIPlus_GraphicsClear($hGraphic, 0xFFFFFFFF) $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBmp_Source) $iW = _GDIPlus_ImageGetWidth($hImage) $iH = _GDIPlus_ImageGetHeight($hImage) $aGS = _IShellFolder_GetScale($iW, $iH, $i_TargetWidth) _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage, $aGS[0], $aGS[1], $aGS[2], $aGS[3]) _GDIPlus_ImageDispose($hImage) _GDIPlus_GraphicsDispose($hGraphic) $hBmp2 = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) _GDIPlus_BitmapDispose($hBitmap) Return $hBmp2 EndFunc ;==>_IShellFolder_GetImage Func _IShellFolder_GetScale($iW, $iH, $i_TargetWidth) Local $aRet[4] If $iW <= $i_TargetWidth And $iH <= $i_TargetWidth Then $aRet[2] = $iW $aRet[3] = $iH $aRet[0] = ($i_TargetWidth - $aRet[2]) / 2 $aRet[1] = ($i_TargetWidth - $aRet[3]) / 2 ElseIf $iW > $iH Then $aRet[2] = $i_TargetWidth $aRet[3] = $iH / ($iW / $i_TargetWidth) $aRet[0] = 0 $aRet[1] = ($i_TargetWidth - $aRet[3]) / 2 ElseIf $iW < $iH Then $aRet[2] = $iW / ($iH / $i_TargetWidth) $aRet[3] = $i_TargetWidth $aRet[0] = ($i_TargetWidth - $aRet[2]) / 2 $aRet[1] = 0 ElseIf $iW = $iH Then $aRet[2] = $i_TargetWidth $aRet[3] = $i_TargetWidth $aRet[0] = 0 $aRet[1] = 0 EndIf Return $aRet EndFunc ;==>_IShellFolder_GetScale Func _IShellFolder_MakeUINT64($long1, $long2) Local $d = DllStructCreate("align 4;dword[2]") DllStructSetData($d, 1, $long1, 1) DllStructSetData($d, 1, $long2, 2) Return DllStructGetData(DllStructCreate("uint64", DllStructGetPtr($d)), 1) EndFunc ;==>_IShellFolder_MakeUINT64 Func _IShellFolder_CoTaskMemFree($pMem) Local $aRes = DllCall("Ole32.dll", "none", "CoTaskMemFree", "ptr", $pMem) If @error Then SetError(1) EndFunc ;==>_IShellFolder_CoTaskMemFree Func _IShellFolder_ILCreateFromPath($sPath) Local $aRes = DllCall("shell32.dll", "ptr", "ILCreateFromPathW", "wstr", $sPath) If @error Then Return SetError(1, 0, 0) Return $aRes[0] EndFunc ;==>_IShellFolder_ILCreateFromPath Func _IShellFolder_SHCreateItemFromParsingName($szPath, $pbc, $riid, ByRef $pv) Local $aRes = DllCall("shell32.dll", "long", "SHCreateItemFromParsingName", "wstr", $szPath, "ptr", $pbc, "ptr", $riid, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[4] Return $aRes[0] EndFunc ;==>_IShellFolder_SHCreateItemFromParsingName Func _IShellFolder_SHBindToObject($psf, $pidl, $pbc, $riid, ByRef $pv) Local $aRes = DllCall("Shell32.dll", "long", "SHBindToObject", "ptr", $psf, "ptr", $pidl, "ptr", $pbc, "ptr", $riid, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[5] Return $aRes[0] EndFunc ;==>_IShellFolder_SHBindToObject Func _SHBindToParent($pidl, $riid, ByRef $pv, ByRef $pidlLast) Local $aRes = DllCall("Shell32.dll", "long", "SHBindToParent", "ptr", $pidl, "ptr", $riid, "ptr*", 0, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[3] $pidlLast = $aRes[4] Return $aRes[0] EndFunc ;==>_SHBindToParent Func _IShellFolder_StrRetToBuf($pSTRRET, $pidl, ByRef $sName, $iLength = 512) Local $aRes = DllCall("shlwapi.dll", "long", "StrRetToBufW", "ptr", $pSTRRET, "ptr", $pidl, "wstr", $sName, "uint", $iLength) If @error Then Return SetError(1, 0, 0) $sName = $aRes[3] Return $aRes[0] EndFunc ;==>_IShellFolder_StrRetToBuf Edited December 20, 2010 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
ProgAndy Posted December 20, 2010 Share Posted December 20, 2010 _GDIPlus_BitmapCreateFromHBITMAP does not take care of premultiplied alpha or "normal" alpha-channels. You have to use GetDIBits, check whether to create the GDI+-image premultiplied or not, then use GDI+-LockBits and copy all Bitmapdata from the GDI-DIB to the GDI+-Bitmap manually. then UnlockBits and free the GDI-Bitmap and you should have a transparent GDI+-Bitmap. Of course you could manipulate the DIBits and use SetDIBits to set them Back to the GDI32-Hbitmap (e.g. premulitply them or merge with background-coor) if you don't need GDI+. *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
KaFu Posted December 21, 2010 Author Share Posted December 21, 2010 Took a while, I'm not that good with graphics yet , thanks god it Christmas . Thanks to Andy for the heads-up and Yashied for his excellent _WinAPI_AlphaBlend() example in the WinApiEx UDF help-file! expandcollapse popup#region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_UseX64=n #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** ; http://www.autoitscript.com/forum/topic/123365-autoitobject-suitable-to-retrieve-iextractimage-interface-pointer-from-shellfolder/page__view__findpost__p__856882 ; ProgAndy #cs Another thing to watch out for is that the API sometimes returns bitmaps that use pre-multiplied alpha and sometimes ones that use normal alpha, with no proper way (except heuristics, which can go wrong) to tell which. It's a pretty poor API. :( – Leo Davidson Dec 13 at 20:12 #ce #include <WindowsConstants.au3> #include <Constants.au3> #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <GuiListView.au3> #include <GuiImageList.au3> #include<SMF_Func_AutoItObject.au3> #include<SMF_Func_WinAPIEx_v3.0.au3> #include-once ;=============================================================================== #API "Extracting Image" ; IShellFolder ; IExtractImage ;=============================================================================== ;.......written by ProgAndy ;=============================================================================== #interface "IShellFolder" $sIID_IShellFolder = "{000214E6-0000-0000-C000-000000000046}" ; Definition Global Const $dtagIShellFolder = $dtagIUnknown & _ "ParseDisplayName hresult(hwnd;ptr;wstr;dword*;ptr*;dword*);" & _ "EnumObjects hresult(hwnd;dword;ptr*);" & _ "BindToObject hresult(ptr;ptr;ptr;ptr*);" & _ "BindToStorage hresult(ptr;ptr;ptr;ptr*);" & _ "CompareIDs hresult(lparam;ptr;ptr);" & _ "CreateViewObject hresult(hwnd;ptr;ptr*);" & _ "GetAttributesOf hresult(UINT;ptr;ulong*);" & _ "GetUIObjectOf hresult(hwnd;uint;ptr;ptr;uint*;ptr*);" & _ "GetDisplayNameOf hresult(ptr;uint;ptr);" & _ "SetNameOf hresult(hwnd;ptr;wstr;dword;ptr*);" ; List Global Const $ltagIShellFolder = $ltagIUnknown & _ "ParseDisplayName;" & _ "EnumObjects;" & _ "BindToObject;" & _ "BindToStorage;" & _ "CompareIDs;" & _ "CreateViewObject;" & _ "GetAttributesOf;" & _ "GetUIObjectOf;" & _ "GetDisplayNameOf;" & _ "SetNameOf;" ;=============================================================================== ;=============================================================================== #interface "IExtractImage" Global Const $sIID_IExtractImage = "{BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}" ; Definition Global Const $dtagIExtractImage = $dtagIUnknown & _ "GetLocation hresult(wstr;DWORD;DWORD*;ptr;dword;DWORD*);" & _ "Extract hresult(ptr*);" ; List Global Const $ltagIExtractImage = $ltagIUnknown & _ "GetLocation;" & _ "Extract;" ;=============================================================================== ;=============================================================================== #interface "IShellItemImageFactory" Global Const $sIID_IShellItemImageFactory = "{bcc18b79-ba16-442f-80c4-8a59c30c463b}" ; Definition Global Const $dtagIShellItemImageFactory = $dtagIUnknown & _ "GetImage hresult(uint64;dword;ptr*);" ; <==== uint64 instead of long;long ; List Global Const $ltagIShellItemImageFactory = $ltagIUnknown & _ "GetImage;" ;=============================================================================== ;=============================================================================== #interface "IShellItem" Global Const $IID_IShellItem = "{43826d1e-e718-42ee-bc55-a1e261c37bfe}" Global Const $dtagIShellItem = $dtagIUnknown & _ "BindToHandler hresult(ptr;ptr;ptr;ptr*);" & _ "GetParent hresult(ptr*);" & _ "GetDisplayName hresult(dword;ptr*);" & _ "GetAttributes hresult(dword;dword*);" & _ "Compare hresult(ptr;dword;int*);" Global Const $ltagIShellItem = $ltagIUnknown & _ "BindToHandler;" & _ "GetParent;" & _ "GetDisplayName;" & _ "GetAttributes;" & _ "Compare;" ;=============================================================================== _AutoItObject_StartUp() Global $h_IShellFolder_Bmp Global $h_IShellFolder_DCB Global $b_IExtractImage_Force = False ; default is to use IShellItemImageFactory if available (Vista+) or IExtractImage on older system (XP), set to true to force IExtractImage usage on Vista+ Global $i_IShellFolder_Preview_Size = 48 OnAutoItExitRegister("_IShellFolder_Exit") _GDIPlus_Startup() $tIIDImgFact = _AutoItObject_CLSIDFromString($sIID_IShellItemImageFactory) _LV_Example() $b_IExtractImage_Force = True _LV_Example() Func _LV_Example() $sBaseDir = StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", 0, -1)) $sFileName1 = $sBaseDir & "Examples\GUI" $sFileName2 = $sFileName1 & "\Advanced\Images\Blue.bmp" $sFileName3 = $sFileName1 & "\merlin.gif" $sFileName4 = $sFileName1 & "\Torus.png" $sFileName5 = $sBaseDir & "icons\au3.ico" $sFileName6 = $sFileName1 & "\mslogo.jpg" $sFileName7 = $sBaseDir & "AutoIt.chm" #region LV-Example Switch $b_IExtractImage_Force Case True GUICreate("ListView Example - IExtractImage Interface", 500, 800) Case Else GUICreate("ListView Example - IShellItemImageFactory Interface", 500, 800) EndSwitch $hListView = GUICtrlCreateListView("", 2, 2, 496, 796) GUISetState() ; Load images $hImage = _GUIImageList_Create($i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size, 5, 3, 1) _IShellFolder_GUIImageList_Add($hImage, $sFileName1) _IShellFolder_GUIImageList_Add($hImage, $sFileName2) _IShellFolder_GUIImageList_Add($hImage, $sFileName3) _IShellFolder_GUIImageList_Add($hImage, $sFileName4) _IShellFolder_GUIImageList_Add($hImage, $sFileName5) _IShellFolder_GUIImageList_Add($hImage, $sFileName6) _IShellFolder_GUIImageList_Add($hImage, $sFileName7) _GUICtrlListView_SetImageList($hListView, $hImage, 1) ; Add columns _GUICtrlListView_AddColumn($hListView, "Filename", 400) ; Add items _GUICtrlListView_AddItem($hListView, $sFileName1, 0) _GUICtrlListView_AddItem($hListView, $sFileName2, 1) _GUICtrlListView_AddItem($hListView, $sFileName3, 2) _GUICtrlListView_AddItem($hListView, $sFileName4, 3) _GUICtrlListView_AddItem($hListView, $sFileName5, 4) _GUICtrlListView_AddItem($hListView, $sFileName6, 5) _GUICtrlListView_AddItem($hListView, $sFileName7, 6) ; Loop until user exits Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete() #endregion LV-Example EndFunc ;==>_LV_Example Func _IShellFolder_Exit() _GDIPlus_Shutdown() _WinAPI_DeleteObject($h_IShellFolder_Bmp) _AutoItObject_Shutdown() EndFunc ;==>_IShellFolder_Exit Func _IShellFolder_GUIImageList_Add($hIML, $sFilename) $hBMP = _IShellFolder_Extract_hBMP($sFilename) Switch $hBMP Case 1 ; Folder under XP If $i_IShellFolder_Preview_Size >= 48 Then _GUIImageList_AddIcon($hIML, @SystemDir & "\shell32.dll", 3, True) Else _GUIImageList_AddIcon($hIML, @SystemDir & "\shell32.dll", 3, False) EndIf Case 2 ; If $i_IShellFolder_Preview_Size >= 48 Then $hIcon = _WinAPI_ShellExtractAssociatedIcon($sFilename, 0) _GUIImageList_ReplaceIcon($hIML, -1, $hIcon) _WinAPI_DestroyIcon($hIcon) Else $hIcon = _WinAPI_ShellExtractAssociatedIcon($sFilename, 1) _GUIImageList_ReplaceIcon($hIML, -1, $hIcon) _WinAPI_DestroyIcon($hIcon) EndIf Case Else _GUIImageList_Add($hIML, $hBMP) EndSwitch EndFunc ;==>_IShellFolder_GUIImageList_Add Func _IShellFolder_Extract_hBMP($sFilename) If Not FileExists($sFilename) Then Return SetError(1) If IsHWnd($h_IShellFolder_Bmp) Then _WinAPI_DeleteObject($h_IShellFolder_Bmp) Dim $pImgFact If 0 = _IShellFolder_SHCreateItemFromParsingName($sFilename, 0, DllStructGetPtr($tIIDImgFact), $pImgFact) And $pImgFact And Not $b_IExtractImage_Force Then $IImgFact = _AutoItObject_WrapperCreate($pImgFact, $dtagIShellItemImageFactory) $r = $IImgFact.GetImage(_IShellFolder_MakeUINT64($i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size), 8, 0) ; <==== _IShellFolder_MakeUINT64 added ;ConsoleWrite($sFileName & @TAB & $r[3] & @CRLF) If $r[3] = 0 Or StringInStr(FileGetAttrib($sFilename), "D") Then ; no thumbnail available OR target is folder $r = $IImgFact.GetImage(_IShellFolder_MakeUINT64($i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size), 0, 0) ; <==== _IShellFolder_MakeUINT64 added $h_IShellFolder_Bmp = $r[3] Else $r = $IImgFact.GetImage(_IShellFolder_MakeUINT64($i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size), 1, 0) ; <==== _IShellFolder_MakeUINT64 added $h_IShellFolder_Bmp = _IShellFolder_GetImage($r[3], $i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size) EndIf ;EndIf Else $pidl = _IShellFolder_ILCreateFromPath($sFilename) Dim $pIShellFolder, $pRelative $tRIID = _AutoItObject_CLSIDFromString($sIID_IShellFolder) $tRIIDExtract = _AutoItObject_CLSIDFromString($sIID_IExtractImage) ;ConsoleWrite($pidl & @crlf) If StringInStr(FileGetAttrib($sFilename), "D", 1) Then _IShellFolder_CoTaskMemFree($pidl) Return 1 ;MsgBox(0, '', "Cannot create preview for Folders on Windows prior to Vista") ;Exit Else _SHBindToParent($pidl, DllStructGetPtr($tRIID), $pIShellFolder, $pRelative) $IShellFolder = _AutoItObject_WrapperCreate($pIShellFolder, $dtagIShellFolder) ;ConsoleWrite(IsObj($IShellFolder) & @crlf) $tSTRRET = DllStructCreate("uint uType;ptr data;") $r = $IShellFolder.GetDisplayNameOf(Number($pRelative), 0, Number(DllStructGetPtr($tSTRRET))) Dim $name _IShellFolder_StrRetToBuf(DllStructGetPtr($tSTRRET), 0, $name, 512) $tSTRRET = 0 ;MsgBox(0, 'name of item', $name) $tArray = DllStructCreate("ptr") DllStructSetData($tArray, 1, $pRelative) $r = $IShellFolder.GetUIObjectOf(0, 1, Number(DllStructGetPtr($tArray)), Number(DllStructGetPtr($tRIIDExtract)), 0, 0) $IExtractImage = _AutoItObject_WrapperCreate($r[6], $dtagIExtractImage) EndIf If Not IsObj($IExtractImage) Then Return 2 Else $tSize = DllStructCreate("long;long") DllStructSetData($tSize, 1, $i_IShellFolder_Preview_Size) DllStructSetData($tSize, 2, $i_IShellFolder_Preview_Size) $r = $IExtractImage.GetLocation("", 1024, 0, Number(DllStructGetPtr($tSize)), 32, 0x0020 + 0x0200) ;IEIFLAG_SCREEN + IEIFLAG_QUALITY ;MsgBox(0, '', $r[1]) $r = $IExtractImage.Extract(0) $h_IShellFolder_Bmp = $r[1] ; ConsoleWrite($name & @TAB & $h_IShellFolder_Bmp & @CRLF) $IShellFolder = 0 _IShellFolder_CoTaskMemFree($pidl) $h_IShellFolder_Bmp2 = _IShellFolder_GetImage($h_IShellFolder_Bmp, $i_IShellFolder_Preview_Size, $i_IShellFolder_Preview_Size) _WinAPI_DeleteObject($h_IShellFolder_Bmp) $h_IShellFolder_Bmp = $h_IShellFolder_Bmp2 EndIf EndIf $IExtractImage = 0 Return $h_IShellFolder_Bmp EndFunc ;==>_IShellFolder_Extract_hBMP Func _IShellFolder_GetImage($hBmp_Source, $i_TargetWidth = 32, $i_TargetHeight = 32) $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBmp_Source) $iW = _GDIPlus_ImageGetWidth($hImage) $iH = _GDIPlus_ImageGetHeight($hImage) $aGS = _IShellFolder_GetScale($iW, $iH, $i_TargetWidth) _GDIPlus_ImageDispose($hImage) $hDC = _WinAPI_GetDC(0) $hDestDC = _WinAPI_CreateCompatibleDC($hDC) $hBMP = _WinAPI_CreateCompatibleBitmapEx($hDC, $i_TargetWidth, $i_TargetHeight, 0xFFFFFF) $hDestSv = _WinAPI_SelectObject($hDestDC, $hBMP) $hSrcDC = _WinAPI_CreateCompatibleDC($hDC) $hSrcSv = _WinAPI_SelectObject($hSrcDC, $hBmp_Source) ;$Result = _WinAPI_AlphaBlend($hDestDC, 0, 0, $i_TargetWidth, $i_TargetHeight, $hSrcDC, 0, 0, $iW, $iH, 255, 0) $Result = _WinAPI_AlphaBlend($hDestDC, $aGS[0], $aGS[1], $aGS[2], $aGS[3], $hSrcDC, 0, 0, $iW, $iH, 255, 0) _WinAPI_ReleaseDC(0, $hDC) _WinAPI_SelectObject($hDestDC, $hDestSv) _WinAPI_SelectObject($hSrcDC, $hSrcSv) _WinAPI_DeleteDC($hDestDC) _WinAPI_DeleteDC($hSrcDC) Return $hBMP EndFunc ;==>_IShellFolder_GetImage Func _IShellFolder_GetScale($iW, $iH, $i_TargetWidth) Local $aRet[4] If $iW <= $i_TargetWidth And $iH <= $i_TargetWidth Then $aRet[2] = $iW $aRet[3] = $iH $aRet[0] = ($i_TargetWidth - $aRet[2]) / 2 $aRet[1] = ($i_TargetWidth - $aRet[3]) / 2 ElseIf $iW > $iH Then $aRet[2] = $i_TargetWidth $aRet[3] = $iH / ($iW / $i_TargetWidth) $aRet[0] = 0 $aRet[1] = ($i_TargetWidth - $aRet[3]) / 2 ElseIf $iW < $iH Then $aRet[2] = $iW / ($iH / $i_TargetWidth) $aRet[3] = $i_TargetWidth $aRet[0] = ($i_TargetWidth - $aRet[2]) / 2 $aRet[1] = 0 ElseIf $iW = $iH Then $aRet[2] = $i_TargetWidth $aRet[3] = $i_TargetWidth $aRet[0] = 0 $aRet[1] = 0 EndIf Return $aRet EndFunc ;==>_IShellFolder_GetScale Func _IShellFolder_MakeUINT64($long1, $long2) Local $d = DllStructCreate("align 4;dword[2]") DllStructSetData($d, 1, $long1, 1) DllStructSetData($d, 1, $long2, 2) Return DllStructGetData(DllStructCreate("uint64", DllStructGetPtr($d)), 1) EndFunc ;==>_IShellFolder_MakeUINT64 Func _IShellFolder_CoTaskMemFree($pMem) Local $aRes = DllCall("Ole32.dll", "none", "CoTaskMemFree", "ptr", $pMem) If @error Then SetError(1) EndFunc ;==>_IShellFolder_CoTaskMemFree Func _IShellFolder_ILCreateFromPath($sPath) Local $aRes = DllCall("shell32.dll", "ptr", "ILCreateFromPathW", "wstr", $sPath) If @error Then Return SetError(1, 0, 0) Return $aRes[0] EndFunc ;==>_IShellFolder_ILCreateFromPath Func _IShellFolder_SHCreateItemFromParsingName($szPath, $pbc, $riid, ByRef $pv) Local $aRes = DllCall("shell32.dll", "long", "SHCreateItemFromParsingName", "wstr", $szPath, "ptr", $pbc, "ptr", $riid, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[4] Return $aRes[0] EndFunc ;==>_IShellFolder_SHCreateItemFromParsingName Func _IShellFolder_SHBindToObject($psf, $pidl, $pbc, $riid, ByRef $pv) Local $aRes = DllCall("Shell32.dll", "long", "SHBindToObject", "ptr", $psf, "ptr", $pidl, "ptr", $pbc, "ptr", $riid, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[5] Return $aRes[0] EndFunc ;==>_IShellFolder_SHBindToObject Func _SHBindToParent($pidl, $riid, ByRef $pv, ByRef $pidlLast) Local $aRes = DllCall("Shell32.dll", "long", "SHBindToParent", "ptr", $pidl, "ptr", $riid, "ptr*", 0, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[3] $pidlLast = $aRes[4] Return $aRes[0] EndFunc ;==>_SHBindToParent Func _IShellFolder_StrRetToBuf($pSTRRET, $pidl, ByRef $sName, $iLength = 512) Local $aRes = DllCall("shlwapi.dll", "long", "StrRetToBufW", "ptr", $pSTRRET, "ptr", $pidl, "wstr", $sName, "uint", $iLength) If @error Then Return SetError(1, 0, 0) $sName = $aRes[3] Return $aRes[0] EndFunc ;==>_IShellFolder_StrRetToBuf OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
ProgAndy Posted December 21, 2010 Share Posted December 21, 2010 Great, but this is some better code to get the dimensions of a HBITMAP without the need of GDI+: Local $tBMP = DllStructCreate($tagBITMAP) _WinAPI_GetObject($hBmp_Source, DllStructGetSize($tBMP), DllStructGetPtr($tBMP)) Local $iW = DllStructGetData($tBMP, "bmWidth"), $iH = Abs(DllStructGetData($tBMP, "bmHeight")) Local $aGS = _IShellFolder_GetScale($iW, $iH, $i_TargetWidth) *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
KaFu Posted December 21, 2010 Author Share Posted December 21, 2010 (edited) Excellent, thanks a lot . In IExtractImage there seem to be even more cases then directories, where the system can not extract a preview. On this occasions I wrote a fallback to extract the respective icons from the systems imagelist. My code is now already heavily integrate into SMF, but maybe beginning of next year I'll create a full stand-alone example. Edited December 21, 2010 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
trancexx Posted December 21, 2010 Share Posted December 21, 2010 KaFu you pyro you... ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now