Sign in to follow this  
Followers 0
smashly

_ExtractIconToFile() with simple Gui example.

31 posts in this topic




#2 ·  Posted (edited)

Thank you

Edited by 123456

Share this post


Link to post
Share on other sites

Your welcome 123456 :)

Updated first post with a Gui Example using the function..

Enjoy.

Share this post


Link to post
Share on other sites

Good work @smashly, useful script. Thanks for sharing.

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

very nice script - thanks alot!!

i had to edit one small thing

;                _GUICtrlListView_DeleteAllItems(GuiControlGethandle($LV)
                _GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($LV)) ;; works with handle
Edited by nobbe

Share this post


Link to post
Share on other sites

very nice script - thanks alot!!

i had to edit one small thing

;                _GUICtrlListView_DeleteAllItems(GuiControlGethandle($LV)
                _GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($LV)) ;; works with handle

Then you must be using an old version of AutoIt, no need to get the handle with latest version(s).


SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

ok right.. i upgraded to 3.2.12 now :-)

i was confused since i was running 3.2.10 before and he stated

Requires AutoIt 3.2.10.x and upwards.

and apparently 3.2.10 requires the handle()

Edited by nobbe

Share this post


Link to post
Share on other sites

smashly

Good job! I like it :) Thank you for example and sharing! :P

Share this post


Link to post
Share on other sites

ok right.. i upgraded to 3.2.12 now :-)

i was confused since i was running 3.2.10 before and he stated

and apparently 3.2.10 requires the handle()

The _ExtractIconToFile() function works with 3.2.10.0

But the Example Gui I supplied requires 3.2.11.x or higher to work.

Cheers

Share this post


Link to post
Share on other sites

; changes by nobbe 27.06.2008

;

; now with menu to save ALL as icon or PNG format

; Supported dropfiles: cpl, dll, exe, icl, ocx
;
;
; changes by nobbe 27.06.2008
;
; written for version 3.2.12 or upper
; now with menu to save ALL as icon or PNG format
;
;





#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <WinAPI.au3>

; status bar
#include <GUIStatusBar.au3>

; icon as png
#include <GDIPlus.au3>


#include "ExtractIconToFile.au3"

Opt("GUIOnEventMode", 1)

; notify messages
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")


Global $sIn = @SystemDir & "\shell32.dll" ;; default icon file
Global $hGui, $LV, $Extract, $LHT, $IHM

;$hGui = GUICreate("", 500, 400, -1, -1, -1, BitOR($WS_EX_TOPMOST, $WS_EX_ACCEPTFILES))
$hGui = GUICreate("", 500, 400, -1, -1, -1, $WS_EX_ACCEPTFILES)

GUISetOnEvent($GUI_EVENT_DROPPED, "GuiEvent", $hGui)
GUISetOnEvent($GUI_EVENT_CLOSE, "GuiEvent", $hGui)

$LV = GUICtrlCreateListView("", 5, 5, 490, 350, $LVS_ICON)
GUICtrlSetState(-1, $GUI_DROPACCEPTED)
GUICtrlSetTip(-1, "Drop a supported file here to view it's icons." & @LF & "Double Click an icon to extract.")
_GUICtrlListView_SetView($LV, 1)



; Build Menu
$fil_mnu = GUICtrlCreateMenu("&extract")
$menu_save_all_as_ico = GUICtrlCreateMenuItem("Save all as ICO", $fil_mnu)
GUICtrlSetOnEvent(-1, "menu_save_all_as_ico")

$menu_save_all_as_png = GUICtrlCreateMenuItem("Save all as PNG", $fil_mnu)
GUICtrlSetOnEvent(-1, "menu_save_all_as_png")


; status bar ..
Global $aStatusParts[2] = [400, -1]
Global $aTempStatus[2] = ["", ""]

$StatusBar = _GUICtrlStatusBar_Create($hGui, $aStatusParts, $aTempStatus, $SBARS_SIZEGRIP)
_GUICtrlStatusBar_SetMinHeight($StatusBar, 20)
_GUICtrlStatusBar_SetText($StatusBar, "Icon Extractor")

GUISetState(@SW_SHOW, $hGui)

Update()


; ---
While 1
    Sleep(100)
    ChkExtract()
WEnd


Func GuiEvent()
    Switch @GUI_CtrlId
        Case $GUI_EVENT_CLOSE
            Exit
            
        Case $GUI_EVENT_DROPPED
            If StringRegExp(@GUI_DragFile, "(?i)\.(cpl|dll|exe|icl|ocx)", 0) Then
                _GUICtrlListView_DeleteAllItems($LV)
                $sIn = @GUI_DragFile
                Update()
            EndIf
    EndSwitch
EndFunc   ;==>GuiEvent


; function - save all as ico as
Func menu_save_all_as_ico()
    ; MsgBox(0,"ico","ico")

    ; all icons ?
    $IHM = _WinAPI_ExtractIconEx($sIn, -1, 0, 0, 0)
    
    For $i = 1 To $IHM
        $filename = @ScriptDir & "\icon_" & $i & ".ico";

        _GUICtrlStatusBar_SetText($StatusBar, "extracting ICO icon " & $i & " of " & $IHM)

        _ExtractIconToFile($sIn, $i, $filename)

    Next
    _GUICtrlStatusBar_SetText($StatusBar, "")
    
    
EndFunc   ;==>menu_save_all_as_ico


; function - save all as png files
Func menu_save_all_as_png()
    ; MsgBox(0,"png","png")

    ; all icons ?
    $IHM = _WinAPI_ExtractIconEx($sIn, -1, 0, 0, 0)
    
    For $i = 1 To $IHM
        $filename = @ScriptDir & "\icon_" & $i & ".png";


        $Ret = DllCall("shell32", "long", "ExtractAssociatedIcon", "int", 0, "str", $sIn, "int*", $i)
        $hIcon = $Ret[0]
        
        _GDIPlus_Startup()
        $pBitmap = DllCall($ghGDIPDll, "int", "GdipCreateBitmapFromHICON", "ptr", $hIcon, "int*", 0)
        $pBitmap = $pBitmap[2]
        
        _GDIPlus_ImageSaveToFile($pBitmap, $filename)
        _GDIPlus_ImageDispose($pBitmap)
        _GDIPlus_Shutdown()
        _WinAPI_DestroyIcon($Ret[0])

        _GUICtrlStatusBar_SetText($StatusBar, "extracting PNG icon " & $i & " of " & $IHM)

    Next
    _GUICtrlStatusBar_SetText($StatusBar, "")
EndFunc   ;==>menu_save_all_as_png




Func ChkExtract()
    If $Extract Then
        $Extract = 0
        
        ;        Local $FOD = FileSaveDialog("Save extracted icon as..", "", "Icon file (*.ico)", 18, DefName(), $hGui)
        Local $FOD = FileSaveDialog("Save extracted icon as..", "", "Icon file (*.ico)")
        
        If Not @error And $FOD <> "" Then
            WinSetTitle($hGui, "", "Extracting...")
            _ExtractIconToFile($sIn, $LHT, $FOD)
            
            If @error Then
                WinSetTitle($hGui, "", "Error extracting icon - Error Code: " & @error)
            Else
                WinSetTitle($hGui, "", "Icons found in " & StringMid($sIn, StringInStr($sIn, "\", 0, -1) + 1) & ": " & $IHM)
            EndIf
        EndIf
    EndIf
EndFunc   ;==>ChkExtract



Func Update()
    $IHM = _WinAPI_ExtractIconEx($sIn, -1, 0, 0, 0)
    WinSetTitle($hGui, "", "Icons found in " & StringMid($sIn, StringInStr($sIn, "\", 0, -1) + 1) & ": " & $IHM)
    
    For $i = 1 To $IHM
        ;       GUICtrlCreateListViewItem("-" & $i, $LV)
        GUICtrlCreateListViewItem($i, $LV)
        GUICtrlSetImage(-1, $sIn, -$i, 1)
    Next
EndFunc   ;==>Update


Func DefName()
    Local $FN = StringFormat("%0" & StringLen($IHM) & "d", $LHT)
    Return $FN & "_" & StringTrimRight(StringMid($sIn, StringInStr($sIn, "\", 0, -1) + 1), 3) & "ico"
EndFunc   ;==>DefName


; double click on item -> extract as--.
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndLV, $tInfo
    $hWndLV = GUICtrlGetHandle($LV)

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hWndLV
            Switch $iCode
                Case $NM_DBLCLK
                    Local $tPoint = _WinAPI_GetMousePos(True, $hGui)
                    Local $LVHT = _GUICtrlListView_HitTest($hWndLV, DllStructGetData($tPoint, "X"), DllStructGetData($tPoint, "Y"))
                    If $LVHT[0] <> -1 Then
                        $Extract = 1
                        $LHT = ($LVHT[0] + 1)
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Share this post


Link to post
Share on other sites

Thanks this help a lot specially if you use shell32.dll icons for your script

Share this post


Link to post
Share on other sites

Thanks a lot ! But, it stops working for some executables. For example, it crashes for Adobe Reader 8.0 :P. I looked trough the code, but couldn't identify the problem ...


[size="2"]SFXMaker[/size] - The most complete switchless installer creator software[indent][/indent]

Share this post


Link to post
Share on other sites

Hello smashly,

Wow, great work! I've tested it with .dll and .exe and it workedfine, but there's a problem with .icl have ever tried to extract icons from .icl ? Is doesn't work!

I'm sure with this method you never will be able to extract icons form .icl files because winapi's LoadLibraryExA function only loads executable files or DynamicLinkLibraries(.dll)

I also checked the return value from your "_LoadLibraryEx" function, it always returned a value of 0x00000000!

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

I tried it and it works :P The .icl libraries I tried: http://www.softrecipe.com/Desktop-Enhancem...on_gallery.html

Edit: At least the icons are shown in the listview. didn't test the extarction :P

Edited 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

Share this post


Link to post
Share on other sites

Yeah that's what I mean, Winapi doesn't load the icl file and a null-pointer is always returning...

Share this post


Link to post
Share on other sites

I tried it and it works :P The .icl libraries I tried: http://www.softrecipe.com/Desktop-Enhancem...on_gallery.html

Edit: At least the icons are shown in the listview. didn't test the extarction :P

Nope ICL won't extract, I jumped the gun when I originally posted this function.

ICL 16 bit module can't be extracted using 32 bit winapi calls. LoadLibrary will throws memory errors.

As for the function working correctly nope, there's another oversite in the code.

When I wrote this function I didn't allow for that not all Ordinal names of RT_ICON are in numeric order in a RT_GROUP_ICON.

Sometimes their order is all over the show, since I was using a count in a loop from the first ordinal name in the RT_GROUP_ICON header and jumping the count by one then if the ordinal names were not in order then extraction would fail or be incorrect. (example of non numerical ordered rt_icons in a rt_group_icon is the AutoIt Beta Installer).

I've since changed the way the ordinal names are located but I just haven't updated this post as I sorta lost interest in a standalone function.

As for the ICL support I've still to understand the NE format (16 bit module) and the way to extract the icons by byte data.

ATM I can extract the Large or Small icon Handle and output that to an .ico file, but that's not giving the user the true icon resources from the ICL file.

Cheers

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

I found sourcecode, which is able to do it: http://www.codeproject.com/KB/cs/IconLib.aspx, but I#M not familar with :NET and can't translate it to AutoIt-Code :P THe required code should be in IconLib/System/Drawing/IconLib/LibraryFormats -> NEFormat.cs

An overview of the NE-Format is here : http://www.codeguru.com/csharp/.net/net_ge....php/c12787__2/

Edited 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

Share this post


Link to post
Share on other sites

ATM I can extract the Large or Small icon Handle and output that to an .ico file, but that's not giving the user the true icon resources from the ICL file.

Hm, could you attach this script, please. Maybe this can resolve my problem.

Share this post


Link to post
Share on other sites

Hm, could you attach this script, please. Maybe this can resolve my problem.

No sorry I can't attach the code as it's only in it's infancy and has not one ounce of error handling. When the code crashes it hard crashes and it has no tolerance for obscure layouts of ICL files, usually leaving a fair chunk of memory not freed until your next reboot, hence me not posting the code as it is. I think one buggy function of code posted is enough ftm

(the _ExtractIconToFile() function is buggy)

Have a look at at what ProgAndy posted, it'll be more helpfull in understanding the NE format and how to access the data you need within the the structure. That same page ProgAndy posted is where I started reading about exporting icons from files before I even started working on extracting icons.

Cheers

Share this post


Link to post
Share on other sites

#20 ·  Posted (edited)

I started to write an ICL-Extractor. up to now, I can read IMAGE_DOS_HEADER, IMAGE_OS2_HEADER, and full RESOURCE_TABLE. Now i have to extract the icons ...

Edited 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

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0