(* ------------------------------------------------------------------------------ ResourceExtractor : 1.0 Copyright © 1986-2012 : Copyright Adirondack Software & Graphics Last Modification : 04-05-2012 Source File : uResourceExtractor.pas Compiler : Delphi 2010 Operating System : Windows 7 This file is copyright (C) W W Miller, 1986-2012. It may be used without restriction. This code distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. ------------------------------------------------------------------------------ *) // NOTE: TShellTreeView is an optional component in Delphi, e.g. in XE8 you can install it from: // C:\Users\Public\Documents\Embarcadero\Studio\14.0\Samples\Object Pascal\VCL\ShellControls unit uResourceExtractor; // {$WARN SYMBOL_PLATFORM OFF} {$WARN UNIT_PLATFORM OFF} interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, Menus, ImgList, ExtCtrls, ExtDlgs, ShellCtrls, IEView, IEMView, ImageENView, ImageENIO, HyIEUtils, Gauges, uSplash, iexBitmaps, hyiedefs, iesettings, iexLayers, iexRulers; type TFormResExtractor = class( TForm ) OpenDialog1: TOpenDialog; ImageList1: TImageList; Panel1: TPanel; SavePictureDialog1: TSavePictureDialog; PopupMenu1: TPopupMenu; Splitter1: TSplitter; Splitter2: TSplitter; TreeView1: TTreeView; Splitter3: TSplitter; ShellTreeView1: TShellTreeView; MainMenu1: TMainMenu; MenuItem1: TMenuItem; MenuItem2: TMenuItem; SaveImageAs1: TMenuItem; N1: TMenuItem; MenuItem4: TMenuItem; Panel2: TPanel; Zoom1: TComboBox; ImageEnView1: TImageEnView; StatusBar1: TStatusBar; SaveAs1: TButton; ExtractAll1: TButton; TaskDialog1: TTaskDialog; Options1: TMenuItem; DefaultDestinationFolder1: TMenuItem; Close1: TButton; SaveGroupIcons1: TButton; SaveAllImages1: TMenuItem; SaveSelectedGroupIcon2: TMenuItem; N2: TMenuItem; SaveSelectedGroupIconToMultiFrameIcon1: TMenuItem; SaveSelectedGroupIcon1: TButton; SaveAllGroupIconsToMultiframeIconfile1: TMenuItem; SaveAllImagesToAFolder1: TMenuItem; SaveSelectedIimage1: TMenuItem; ReturnToTheSystem32Folder1: TMenuItem; SaveAllGroupIcons1: TMenuItem; NoImages1: TLabel; NoBitmaps1: TLabel; NoPNG1: TLabel; NoGroupIcons1: TLabel; NoIcons1: TLabel; NoGroupCursors1: TLabel; NoCursors1: TLabel; NoResources1: TLabel; Label1: TLabel; SaveAllIcons1: TButton; View1: TMenuItem; ViewIcons1: TMenuItem; Dimensions1: TLabel; Colors1: TLabel; Frames1: TLabel; ViewIcons2: TButton; SaveAllIcons2: TMenuItem; DestinationFolderComboBox1: TComboBox; BrowseForFolder1: TButton; Label2: TLabel; Label3: TLabel; PopupMenuShellListView1: TPopupMenu; Icon1: TMenuItem; SmallIcon1: TMenuItem; List1: TMenuItem; Report1: TMenuItem; ShellListView1: TShellListView; PopupMenuDestCombobox1: TPopupMenu; Delete1: TMenuItem; Clear1: TMenuItem; Gauge1: TGauge; Help1: TMenuItem; About1: TMenuItem; Filename1: TLabel; FileSize1: TLabel; procedure FormCreate( Sender: TObject ); procedure FormDestroy( Sender: TObject ); procedure Exit1Click( Sender: TObject ); procedure Open1Click( Sender: TObject ); procedure TreeView1Change( Sender: TObject; Node: TTreeNode ); procedure TreeView1GetImageIndex( Sender: TObject; Node: TTreeNode ); procedure Saveimageas1Click( Sender: TObject ); procedure DestinationFolder1Click( Sender: TObject ); procedure SaveAs1Click( Sender: TObject ); procedure SavePictureDialog1TypeChange( Sender: TObject ); procedure Zoom1Change( Sender: TObject ); procedure ShellListView1Change( Sender: TObject; Item: TListItem; Change: TItemChange ); procedure ShellTreeView1Change( Sender: TObject; Node: TTreeNode ); procedure DefaultDestinationFolder1Click( Sender: TObject ); procedure FormShow( Sender: TObject ); procedure ShellListView1KeyDown( Sender: TObject; var Key: Word; Shift: TShiftState ); procedure ShellListView1MouseDown( Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer ); procedure ExtractAll1Click( Sender: TObject ); procedure ShellListView1ColumnClick( Sender: TObject; Column: TListColumn ); procedure SaveGroupIcons1Click( Sender: TObject ); procedure SaveSelectedGroupIcon1Click( Sender: TObject ); procedure ReturnToTheSystem32Folder1Click( Sender: TObject ); procedure PopupMenu1Popup( Sender: TObject ); procedure SaveAllIcons1Click( Sender: TObject ); procedure ViewIcons1Click( Sender: TObject ); procedure ImageEnView1Progress( Sender: TObject; per: integer ); procedure ImageEnView1FinishWork( Sender: TObject ); procedure BrowseForFolder1Click( Sender: TObject ); procedure Icon1Click( Sender: TObject ); procedure SmallIcon1Click( Sender: TObject ); procedure List1Click( Sender: TObject ); procedure Report1Click( Sender: TObject ); procedure Delete1Click( Sender: TObject ); procedure DestinationFolderComboBox1CloseUp( Sender: TObject ); procedure Clear1Click( Sender: TObject ); procedure About1Click( Sender: TObject ); private { Private declarations } FIniFilename: string; FState: integer; FStartupFolder: string; FFilePath: string; FDestinationFolder: string; procedure ReadIni( IniFilename: string ); procedure WriteIni( IniFilename: string ); public { Public declarations } FResourceExtractor: TIEResourceExtractor; end; var FormResExtractor: TFormResExtractor; implementation {$R *.dfm} uses ShlObj, IniFiles, ShellAPI, ShLwApi, StrUtils, FileCtrl, uViewIcons, uAbout; var ShellListSortColumn: integer; ShellListSortAscending: boolean; function ShellCompare( Item1, Item2: Pointer ): integer; // Compare shell columns const i: array [ boolean ] of Byte = ( 0, 1 ); begin Result := 0; if ( Item1 = nil ) or ( Item2 = nil ) then Exit; if ShellListSortAscending then begin Result := i[ TShellFolder( Item2 ).IsFolder ] - i[ TShellFolder( Item1 ).IsFolder ]; if Result = 0 then if ( TShellFolder( Item1 ).ParentShellFolder <> nil ) then Result := Smallint( TShellFolder( Item1 ).ParentShellFolder.CompareIDs( ShellListSortColumn, // sort_type, TShellFolder( Item1 ).RelativeID, TShellFolder( Item2 ).RelativeID ) ); end else begin Result := i[ TShellFolder( Item1 ).IsFolder ] - i[ TShellFolder( Item2 ).IsFolder ]; if Result = 0 then if ( TShellFolder( Item2 ).ParentShellFolder <> nil ) then Result := Smallint( TShellFolder( Item2 ).ParentShellFolder.CompareIDs( ShellListSortColumn, // sort_type, TShellFolder( Item2 ).RelativeID, TShellFolder( Item1 ).RelativeID ) ); end; end; function GetSizeOfPIDL( PIDL: pItemIDList ): integer; // Get the size of a pidl var iSize: integer; begin if ( PIDL <> nil ) then begin Result := SizeOf( PIDL^.mkid.cb ); while ( PIDL^.mkid.cb <> 0 ) do begin iSize := PIDL^.mkid.cb; inc( Result, iSize ); inc( PByte( PIDL ), iSize ); end; end else Result := 0; end; function PathToPIDL( APath: WideString ): pItemIDList; // Takes the passed Path and attempts to convert it to the equavalent PIDL var iDesktop: IShellFolder; iEaten, dwAttributes: ULONG; begin Result := nil; SHGetDesktopFolder( iDesktop ); dwAttributes := 0; if Assigned( iDesktop ) then begin if iDesktop.ParseDisplayName( 0, nil, PWideChar( APath ), iEaten, Result, dwAttributes ) <> NOERROR then Result := nil end; end; function PIDLToString( PIDL: pItemIDList ): string; // Convert a pidl to a string var iPidlLength: integer; begin iPidlLength := GetSizeOfPIDL( PIDL ); SetLength( Result, iPidlLength ); Move( PIDL^, PChar( Result )^, iPidlLength ); end; function CurrentDrive: Char; // Returns the letter that identifies the current drive. var iDir: string; // current drive as string begin GetDir( 0, iDir ); Result := iDir[ 1 ]; end; function LocalAppDataFolder: string; // Find LocalAppData folder location var i: Bool; iPath: array [ 0 .. MAX_PATH ] of Char; begin i := ShGetSpecialFolderPath( 0, iPath, CSIDL_LOCAL_APPDATA, False ); if not i then raise Exception.Create( 'Could not find LocalAppData folder location.' ); Result := iPath; end; function AppDataFolder: string; // Find AppData folder location var i: Bool; iPath: array [ 0 .. MAX_PATH ] of Char; begin i := ShGetSpecialFolderPath( 0, iPath, CSIDL_APPDATA, False ); if not i then raise Exception.Create( 'Could not find AppData folder location.' ); Result := iPath; end; function ProfileFolder: string; // Find Profile folder location var i: Bool; iPath: array [ 0 .. MAX_PATH ] of Char; begin i := ShGetSpecialFolderPath( 0, iPath, CSIDL_PROFILE, False ); if not i then raise Exception.Create( 'Could not find Profile folder location.' ); Result := iPath; end; function WindowsFolder: string; // Returns the Windows directory begin SetLength( Result, Windows.MAX_PATH ); SetLength( Result, Windows.GetWindowsDirectory( PChar( Result ), Windows.MAX_PATH ) ); end; function System32Folder: string; // Returns the Windows System32 directory begin Result := IncludeTrailingPathDelimiter( WindowsFolder ) + 'System32'; end; function DocumentsFolder: string; // Find Documents folder location var i: Bool; iPath: array [ 0 .. MAX_PATH ] of Char; begin i := ShlObj.ShGetSpecialFolderPath( 0, iPath, CSIDL_PERSONAL, False ); if not i then raise Exception.Create( 'Could not find Documents folder location.' ); Result := IncludeTrailingPathDelimiter( iPath ); end; function DesktopFolder: string; // Find Desktop folder location var i: Bool; iPath: array [ 0 .. MAX_PATH ] of Char; begin i := ShlObj.ShGetSpecialFolderPath( 0, iPath, CSIDL_DESKTOP, False ); if not i then raise Exception.Create( 'Could not find Documents folder location.' ); Result := IncludeTrailingPathDelimiter( iPath ); end; function BrowseForFolder( AFolder: string ): string; // BrowseForFolder var iFolder: string; begin if DirectoryExists( AFolder ) then if FileCtrl.SelectDirectory( 'Select Folder', iFolder, AFolder, [ sdNewFolder, sdNewUI ], FormResExtractor ) then Result := AFolder; end; function JustFilename( const APathName: string ): string; // Return a filename from a string var iString: string; i: integer; // Turn // Reverse characters in a string ABCD -> DCBA function Turn( const AString: string ): string; var i: integer; begin Result := ''; if AString <> '' then for i := 1 to Length( AString ) do Result := AString[ i ] + Result; end; begin iString := Turn( APathName ); i := Pos( '\', iString ); if i = 0 then i := Pos( ':', iString ); if i = 0 then Result := APathName else Result := Turn( Copy( iString, 1, i - 1 ) ); end; function JustName( const APathName: string ): string; // Return just the name from a file string var iString: string; begin iString := JustFilename( APathName ); if Pos( '.', iString ) <> 0 then Result := Copy( iString, 1, Pos( '.', iString ) - 1 ) else Result := iString; end; procedure SearchDirectory( List: TStrings; const Directory: string; const Mask: string = '*.*'; Recursive: boolean = True; Append: boolean = False ); // "Directory": will be searched for files and directories, the results will // be added with the full path to "List". directories are written with a // trailing "\" at the end. // "Mask": can contain one or several masks, delimited with a semikolon. to // ignore directory names, add an extension to the mask. for more detailed // information see the delphi function "FindFirst". // "Recursive": if true, subdirectories will be searched too. // "Append": if true, existing entries remain in "List". // procedure _SearchDirectory( List: TStrings; const DelimitedDirectory: string; Masks: TStrings; Recursive: boolean ); var iMaskIndex: integer; iFoundFile: boolean; iSearchRec: TSearchRec; iFile, iDirectory: string; begin // list files and directories for iMaskIndex := 0 to Masks.Count - 1 do begin iFoundFile := FindFirst( DelimitedDirectory + Masks[ iMaskIndex ], faAnyFile, iSearchRec ) = 0; while ( iFoundFile ) do begin // skip "." and ".." if ( iSearchRec.Name <> '.' ) and ( iSearchRec.Name <> '..' ) then begin iFile := DelimitedDirectory + iSearchRec.Name; // add delimiter to directories if ( ( iSearchRec.Attr and faDirectory ) <> 0 ) then iFile := IncludeTrailingPathDelimiter( iFile ); // add to list List.Add( iFile ); end; // find next file iFoundFile := FindNext( iSearchRec ) = 0; end; FindClose( iSearchRec ); end; // recursive call for directories if ( Recursive ) then begin iFoundFile := FindFirst( DelimitedDirectory + '*', faDirectory, iSearchRec ) = 0; while ( iFoundFile ) do begin // skip "." and ".." if ( iSearchRec.Name <> '.' ) and ( iSearchRec.Name <> '..' ) then begin iDirectory := IncludeTrailingPathDelimiter( DelimitedDirectory + iSearchRec.Name ); _SearchDirectory( List, iDirectory, Masks, Recursive ); end; // find next directory iFoundFile := FindNext( iSearchRec ) = 0; end; FindClose( iSearchRec ); end; end; var islMasks: TStringList; begin // prepare list if ( not Append ) then List.Clear; List.BeginUpdate; islMasks := TStringList.Create; try // prepare masks if ( Mask = '' ) then islMasks.Add( '*' ) else begin islMasks.Delimiter := ';'; islMasks.DelimitedText := Mask; end; // start recursive loop _SearchDirectory( List, IncludeTrailingPathDelimiter( Directory ), islMasks, Recursive ); finally islMasks.Free; List.EndUpdate; end; end; // Remove duplicate strings from the string list procedure RemoveDuplicates( const StringList: TStringList ); var iBuffer: TStringList; iCount: integer; begin StringList.Sort; iBuffer := TStringList.Create; try iBuffer.Sorted := True; iBuffer.Duplicates := dupIgnore; iBuffer.BeginUpdate; for iCount := 0 to StringList.Count - 1 do iBuffer.Add( StringList[ iCount ] ); iBuffer.EndUpdate; StringList.Assign( iBuffer ); finally FreeandNil( iBuffer ); end; end; procedure NoDuplicates( AComboBox: TComboBox ); var iStringList: TStringList; begin iStringList := TStringList.Create; try iStringList.Duplicates := dupIgnore; iStringList.Sorted := True; iStringList.Assign( AComboBox.Items ); AComboBox.Items.Assign( iStringList ); finally iStringList.Free end; end; function AddThousandSeparator( const S: string; const C: Char ): string; // Adds a specified thousand separator in the correct location in a string var i: integer; // loops through separator position begin Result := S; i := Length( S ) - 2; while i > 1 do begin Insert( C, Result, i ); i := i - 3; end; end; function AddDefThousandSeparator( const S: string ): string; // Adds the thousands separator from the default locale in the correct location in a string begin // Note: FormatSettings.ThousandSeparator in XE8 or Newer Result := AddThousandSeparator( S, SysUtils.ThousandSeparator ); end; function IntegerToString( const Value: integer ): string; // Convert value into a string with thousandsseperator begin Result := AddDefThousandSeparator( IntToStr( Value ) ); end; function FileSize( FileName: WideString ): Int64; // Returns file size in bytes or -1 if not found. var isr: TSearchRec; begin if FindFirst( FileName, faAnyFile, isr ) = 0 then Result := Int64( isr.FindData.nFileSizeHigh ) shl Int64( 32 ) + Int64( isr.FindData.nFileSizeLow ) else Result := -1; FindClose( isr ); end; function FormatByteSize( ABytes: cardinal ): string; { Converts a numeric value into a string that represents the number expressed as a size value in bytes, kilobytes, megabytes, or gigabytes, depending on the size. } var ArrSize: array [ 0 .. 255 ] of Char; begin { statusbar style } Result := ''; { same formating used in statusbar of Explorer } Result := ShLwApi.StrFormatByteSizeW( ABytes, ArrSize, Length( ArrSize ) - 1 ); end; function FormatKBSize( ABytes: cardinal ): string; { Converts a numeric value into a string that represents the number expressed as a size value in kilobytes. } var ArrSize: array [ 0 .. 255 ] of Char; begin { explorer style } Result := ''; { same formating used in the Size column of Explorer in detailed mode } Result := ShLwApi.StrFormatKBSizeW( ABytes, ArrSize, Length( ArrSize ) - 1 ); end; function FormatMBSize( ABytes: Int64 ): string; { Converts a numeric value into a string that represents the number expressed as a size value in megabytes. } const B = 1; { byte } KB = 1024 * B; { kilobyte } MB = 1024 * KB; { megabyte } GB = 1024 * MB; { gigabyte } begin Result := FormatFloat( '###,# MB', ABytes / MB ); end; function IEFileTypeToExtension( AIEFileType: TIOFileType ): string; // Convert TIOFileType to a file extension begin // Result := ExtractFileExt( IEFileFormatGetInfo( AIEFileType ).FullName ); case AIEFileType of ioTIFF: Result := '.tif'; ioGIF: Result := '.gif'; ioJPEG: Result := '.jpg'; ioPCX: Result := '.pcx'; ioBMP: Result := '.bmp'; ioICO: Result := '.ico'; ioCUR: Result := '.cur'; ioPNG: Result := '.png'; ioWMF: Result := '.wmf'; ioEMF: Result := '.emf'; ioTGA: Result := '.tga'; ioPXM: Result := '.ppm'; ioJP2: Result := '.jp2'; ioJ2K: Result := '.j2k'; ioAVI: Result := '.avi'; ioWBMP: Result := '.wbmp'; ioPS: Result := '.ps'; ioPDF: Result := '.pdf'; ioDCX: Result := '.dcx'; ioRAW: Result := '.raw'; ioBMPRAW: Result := '.braw'; ioWMV: Result := '.wmv'; ioMPEG: Result := '.mpeg'; ioPSD: Result := '.psd'; ioIEV: Result := '.iev'; ioHDP: Result := '.wdp'; ioLYR: Result := '.lyr'; ioALL: Result := '.all'; ioDICOM: Result := '.dcm'; end; // case end; function IEFileTypeToString( AIEFileType: TIOFileType ): string; // Convert TIOFileType to a string begin Result := IEFileFormatGetInfo( AIEFileType ).FullName; end; function BitDepthToString( const ASamplesPerPixel: integer; const ABitsPerSample: integer ): string; // Convert a bitdepth to a string. begin if ( ASamplesPerPixel = 4 ) and ( ABitsPerSample = 8 ) then Result := 'RGBA 32-Bit' else if ( ASamplesPerPixel = 3 ) and ( ABitsPerSample = 8 ) then Result := 'RGB 24-Bit' else if ( ASamplesPerPixel = 1 ) and ( ABitsPerSample = 8 ) then Result := 'RGB 8-Bit' else if ( ASamplesPerPixel = 1 ) and ( ABitsPerSample = 4 ) then Result := 'RGB 4-Bit' else if ( ASamplesPerPixel = 1 ) and ( ABitsPerSample = 2 ) then Result := 'RGB 2-Bit' else Result := 'Unknown'; end; function Instr( str: string; substr: string ): integer; begin Instr := Pos( substr, str ); end; function StringStripAll( instring, charac: string ): string; var idone: boolean; ipos: integer; begin repeat ipos := Instr( instring, charac ); if ipos > 0 then begin idone := False; delete( instring, ipos, 1 ); end else idone := True; until idone; StringStripAll := instring; end; function RemoveDotFromExtension( AExt: string ): string; // Remove the dot '.' from the extension begin // Delete removes a substring of Count characters from string S starting with S[Index]. delete( AExt, 1, 1 ); Result := AExt; end; function RemoveColonFromString( AString: string ): string; // Remove the dot ':' from the extension begin Result := StringStripAll( AString, ':' ); end; function IEFileTypeToShortExtension( AIEFileType: TIOFileType ): string; // Convert AIEFileType to a short string- no dot var iExtension: string; begin iExtension := IEFileFormatGetInfo( AIEFileType ).Extensions; Result := RemoveDotFromExtension( iExtension ); end; function GetFileCount( AFolder, AWildCard: string ): integer; // Get the file count in AFolder with a wildcard var iIntFound: integer; iSearchRec: TSearchRec; begin Screen.Cursor := crHourGlass; try Result := 0; if ( AFolder <> '' ) and ( AFolder[ Length( AFolder ) ] <> '\' ) then AFolder := AFolder + '\'; iIntFound := FindFirst( AFolder + AWildCard, faAnyFile, iSearchRec ); while ( iIntFound = 0 ) do begin if not( iSearchRec.Attr and faDirectory = faDirectory ) then inc( Result ); iIntFound := FindNext( iSearchRec ); end; FindClose( iSearchRec ); finally Screen.Cursor := crDefault; end; end; function StringContainsText( ADest, ASource: string ): boolean; // Return true if ASouce contains ADest begin // if 0 then equal Result := Pos( ADest, ASource ) > 0; end; function IsWhiteSpace( const AChar: Char ): boolean; { Checks if a character is white space. } begin Result := SysUtils.CharInSet( AChar, [ ' ', #9, #10, #11, #12, #13 ] ); end; function CapFirst( const AValue: string ): string; // Convert all first letters to caps var i: integer; iString: string; begin iString := UpperCase( AValue[ 1 ] ); for i := 2 to Length( AValue ) do if SysUtils.CharInSet( AValue[ i - 1 ], [ ' ', ',', ':', ';', '.', '\' ] ) then iString := iString + UpperCase( AValue[ i ] ) else iString := iString + LowerCase( AValue[ i ] ); Result := iString; end; function TitleCase( const AString: string ): string; // Converts a string to title case var idx: integer; // loops through each character in string iWantCapital: boolean; // flag indicating whether captial letter required begin Result := SysUtils.LowerCase( AString ); iWantCapital := True; for idx := 1 to Length( AString ) do begin if SysUtils.CharInSet( Result[ idx ], [ 'a' .. 'z', 'A' .. 'Z' ] ) then begin if iWantCapital then Result[ idx ] := UpCase( Result[ idx ] ); // capital letter required iWantCapital := False; // following chars lower case end else iWantCapital := IsWhiteSpace( Result[ idx ] ); // space: next char is capital end; end; function IsFileAResource( AFilename: string ): boolean; // Is AFilename a resource file var iResFileExtension: string; begin iResFileExtension := LowerCase( ExtractFileExt( AFilename ) ); Result := ( iResFileExtension = '.exe' ) or ( iResFileExtension = '.dll' ) or ( iResFileExtension = '.icl' ) or ( iResFileExtension = '.bpl' ) or ( iResFileExtension = '.ocx' ) or ( iResFileExtension = '.scr' ) or ( iResFileExtension = '.cpl' ); end; function NumberOfResourcesInRes( APath: string ): integer; // Return the number of resources in the resource file var i: integer; j: integer; iTotalResources: integer; iResourceExtractor: TIEResourceExtractor; begin Result := 0; iTotalResources := 0; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do if iResourceExtractor.IsGroup[ i ] then inc( iTotalResources, iResourceExtractor.GroupCountFrames[ i, j ] ) else inc( iTotalResources ); Result := iTotalResources; end; finally iResourceExtractor.Free; end; end; function NumberOfImagesInRes( APath: string ): integer; // Return the number of images in the resource file var i: integer; j: integer; iTotalImages: integer; iResourceExtractor: TIEResourceExtractor; begin Result := 0; iTotalImages := 0; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do if ( iResourceExtractor.IsGroup[ i ] ) and ( ( iResourceExtractor.FriendlyTypes[ i ] = 'GroupIcon' ) or ( iResourceExtractor.FriendlyTypes[ i ] = 'Image' ) or ( iResourceExtractor.FriendlyTypes[ i ] = 'Icon' ) or ( iResourceExtractor.FriendlyTypes[ i ] = 'GroupCursor' ) or ( iResourceExtractor.FriendlyTypes[ i ] = 'Cursor' ) or ( iResourceExtractor.FriendlyTypes[ i ] = 'Bitmap' ) or ( iResourceExtractor.FriendlyTypes[ i ] = 'PNG' ) ) then inc( iTotalImages, iResourceExtractor.GroupCountFrames[ i, j ] ) else if ( iResourceExtractor.FriendlyTypes[ i ] = 'Image' ) or ( iResourceExtractor.FriendlyTypes[ i ] = 'Icon' ) or ( iResourceExtractor.FriendlyTypes[ i ] = 'Cursor' ) or ( iResourceExtractor.FriendlyTypes[ i ] = 'Bitmap' ) or ( iResourceExtractor.FriendlyTypes[ i ] = 'PNG' ) then inc( iTotalImages ); Result := iTotalImages; end; finally iResourceExtractor.Free; end; end; function NumberOfGroupIconsInRes( APath: string ): integer; // Return the number of groupicons in the resource file var i: integer; j: integer; iTotalImages: integer; iResourceExtractor: TIEResourceExtractor; begin Result := 0; iTotalImages := 0; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do if ( iResourceExtractor.IsGroup[ i ] ) and ( ( iResourceExtractor.FriendlyTypes[ i ] = 'GroupIcon' ) ) then inc( iTotalImages ); Result := iTotalImages; end; finally iResourceExtractor.Free; end; end; function NumberOfGroupCursorsInRes( APath: string ): integer; // Return the number of groupcursors in the resource file var i: integer; j: integer; iTotalImages: integer; iResourceExtractor: TIEResourceExtractor; begin Result := 0; iTotalImages := 0; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do if ( iResourceExtractor.IsGroup[ i ] ) and ( ( iResourceExtractor.FriendlyTypes[ i ] = 'GroupCursor' ) ) then inc( iTotalImages, iResourceExtractor.GroupCountFrames[ i, j ] ); Result := iTotalImages; end; finally iResourceExtractor.Free; end; end; function NumberOfBMPInRes( APath: string ): integer; // Return the number of bmp in the resource file var i: integer; j: integer; iTotalImages: integer; iResourceExtractor: TIEResourceExtractor; begin Result := 0; iTotalImages := 0; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do if iResourceExtractor.FriendlyTypes[ i ] = 'Bitmap' then inc( iTotalImages ); Result := iTotalImages; end; finally iResourceExtractor.Free; end; end; function NumberOfIconsInRes( APath: string ): integer; // Return the number of ico in the resource file var i: integer; j: integer; iTotalImages: integer; iResourceExtractor: TIEResourceExtractor; begin Result := 0; iTotalImages := 0; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do if iResourceExtractor.FriendlyTypes[ i ] = 'Icon' then inc( iTotalImages ); Result := iTotalImages; end; finally iResourceExtractor.Free; end; end; function NumberOfCursorsInRes( APath: string ): integer; // Return the number of cur in the resource file var i: integer; j: integer; iTotalImages: integer; iResourceExtractor: TIEResourceExtractor; begin Result := 0; iTotalImages := 0; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do if iResourceExtractor.FriendlyTypes[ i ] = 'Cursor' then inc( iTotalImages ); Result := iTotalImages; end; finally iResourceExtractor.Free; end; end; function NumberOfBitmapsInRes( APath: string ): integer; // Return the number of bmp in the resource file var i: integer; j: integer; iTotalImages: integer; iResourceExtractor: TIEResourceExtractor; begin Result := 0; iTotalImages := 0; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do if iResourceExtractor.FriendlyTypes[ i ] = 'Bitmap' then inc( iTotalImages ); Result := iTotalImages; end; finally iResourceExtractor.Free; end; end; function NumberOfPNGInRes( APath: string ): integer; // Return the number of png in the resource file var i: integer; j: integer; iTotalImages: integer; iResourceExtractor: TIEResourceExtractor; begin Result := -1; iTotalImages := 0; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do if iResourceExtractor.FriendlyTypes[ i ] = 'PNG' then inc( iTotalImages ); Result := iTotalImages; end; finally iResourceExtractor.Free; end; end; function NumberOfExtractableImagesInRes( APath: string ): integer; // Return the number of extractable images ( bmp, png, groupicons and icons,) in the resource file var iNumberOfExtractableImagesInRes: integer; iNumberOfBitmaps: integer; iNumberOfPNG: integer; iNumberOfGroupIcons: integer; iNumberOfIcons: integer; begin iNumberOfBitmaps := NumberOfBitmapsInRes( APath ); iNumberOfPNG := NumberOfPNGInRes( APath ); iNumberOfGroupIcons := NumberOfGroupIconsInRes( APath ); iNumberOfIcons := NumberOfIconsInRes( APath ); iNumberOfExtractableImagesInRes := iNumberOfBitmaps + iNumberOfPNG + iNumberOfGroupIcons + iNumberOfIcons; Result := iNumberOfExtractableImagesInRes; end; function NodeChildCount( SelNode: TTreeNode ): integer; // Return the number of child nodes in the selected node var iNode: TTreeNode; begin Result := 0; if SelNode = nil then Exit; iNode := SelNode.GetNext; while ( iNode <> nil ) and ( iNode.Parent = SelNode ) do begin inc( Result ); iNode := iNode.GetNext; end; end; function CountChildNodes( ATreeView: TTreeView ): integer; // Return the number of child nodes - level 1 in the selected node var i: integer; begin Result := 0; if ATreeView.Selected = nil then begin for i := 0 to ATreeView.Items.Count - 1 do if ATreeView.Items[ i ].Level = 0 then inc( Result ); end else Result := ATreeView.Selected.Count; end; function ResourceHasBMP( APath: string ): boolean; // Return true if the resource has bitmaps, false if not begin Result := NumberOfBMPInRes( APath ) > 0; end; function ResourceHasPNG( APath: string ): boolean; // Return true if the resource has png, false if not begin Result := NumberOfPNGInRes( APath ) > 0; end; function ResourceHasIcons( APath: string ): boolean; // Return true if the resource has ico, false if not begin Result := NumberOfIconsInRes( APath ) > 0; end; function ResourceHasGroupIcons( APath: string ): boolean; // Return true if the resource has groupicons, false if not begin Result := NumberOfGroupIconsInRes( APath ) > 0; end; function ResourceHasImages( APath: string ): boolean; // Return true if the resource has images, false if not begin Result := NumberOfImagesInRes( APath ) > 0; end; function DoesResourceContainGroupIcon( APath: string ): boolean; // Returns True if the resource file contains a GroupIcon, or false of not var i: integer; iFriendlyType: string; iResourceExtractor: TIEResourceExtractor; begin Result := False; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do begin iFriendlyType := string( iResourceExtractor.FriendlyTypes[ i ] ); Result := iFriendlyType = 'GroupIcon'; if Result then Break; end; end; finally iResourceExtractor.Free; end; end; function DoesResourceContainIcon( APath: string ): boolean; // Returns True if the resource file contains a Icon, or false of not var i: integer; iFriendlyType: string; iResourceExtractor: TIEResourceExtractor; begin Result := False; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do begin iFriendlyType := string( iResourceExtractor.FriendlyTypes[ i ] ); Result := iFriendlyType = 'Icon'; if Result then Break; end; end; finally iResourceExtractor.Free; end; end; function DoesResourceContainCursor( APath: string ): boolean; // Returns True if the resource file contains a Cursor, or false of not var i: integer; iFriendlyType: string; iResourceExtractor: TIEResourceExtractor; begin Result := False; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do begin iFriendlyType := string( iResourceExtractor.FriendlyTypes[ i ] ); Result := iFriendlyType = 'Cursor'; if Result then Break; end; end; finally iResourceExtractor.Free; end; end; function DoesResourceContainGroupCursor( APath: string ): boolean; // Returns True if the resource file contains a Cursor, or false of not var i: integer; iFriendlyType: string; iResourceExtractor: TIEResourceExtractor; begin Result := False; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do begin iFriendlyType := string( iResourceExtractor.FriendlyTypes[ i ] ); Result := iFriendlyType = 'GroupCursor'; if Result then Break; end; end; finally iResourceExtractor.Free; end; end; function DoesResourceContainBitmap( APath: string ): boolean; // Returns True if the resource file contains a Bitmap, or false of not var i: integer; iFriendlyType: string; iResourceExtractor: TIEResourceExtractor; begin Result := False; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do begin iFriendlyType := string( iResourceExtractor.FriendlyTypes[ i ] ); Result := iFriendlyType = 'Bitmap'; if Result then Break; end; end; finally iResourceExtractor.Free; end; end; function DoesResourceContainPNG( APath: string ): boolean; // Returns True if the resource file contains a PNG, or false of not var i: integer; iFriendlyType: string; iResourceExtractor: TIEResourceExtractor; begin Result := False; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do begin iFriendlyType := string( iResourceExtractor.FriendlyTypes[ i ] ); Result := iFriendlyType = 'PNG'; if Result then Break; end; end; finally iResourceExtractor.Free; end; end; function IsResourceGroupIcon( APath: string; AIndex: integer ): boolean; // Returns True if AIndex is a GroupIcon resource, or false of not var iIndex: integer; iResourceExtractor: TIEResourceExtractor; iFriendlyType: string; iIsGroup: boolean; iIsGrouped: boolean; begin Result := False; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin // search for GroupIcon iIndex := AIndex; iFriendlyType := string( iResourceExtractor.FriendlyTypes[ iIndex ] ); iIsGroup := iResourceExtractor.IsGroup[ iIndex ]; iIsGrouped := iResourceExtractor.IsGrouped[ iIndex ]; if ( iFriendlyType = 'GroupIcon' ) or ( iIsGroup ) or ( iIsGrouped ) then Result := True else Result := False; end; finally iResourceExtractor.Free( ); end; end; function IsResourceIcon( APath: string; ASelection: string; AIndex: integer ): boolean; // Returns True if ASelection is a Icon resource, or false of not var i: integer; j: integer; iFriendlyType: string; iResourceExtractor: TIEResourceExtractor; iResourceExtractorName: string; begin Result := False; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do begin iFriendlyType := string( iResourceExtractor.FriendlyTypes[ AIndex ] ); if i <> 0 then if iFriendlyType = string( iResourceExtractor.FriendlyTypes[ i ] ) then Break; for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do begin // Use the selection to select the resource iResourceExtractorName := string( iResourceExtractor.Names[ i, j ] ); if iResourceExtractorName = ASelection then begin iFriendlyType := string( iResourceExtractor.FriendlyTypes[ i ] ); Break; end; end; end; Result := iFriendlyType = 'Icon'; end; finally iResourceExtractor.Free; end; end; function IsResourceGroupCursor( APath: string; AIndex: integer ): boolean; // Returns True if ASelection is a GroupCursor resource, or false of not var iResourceExtractor: TIEResourceExtractor; begin Result := False; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin // search for GroupCursor if iResourceExtractor.FriendlyTypes[ AIndex ] = 'GroupCursor' then Result := True else Result := False; end; finally iResourceExtractor.Free( ); end; end; function IsResourceCursor( APath: string; ASelection: string ): boolean; // Returns True if ASelection is a Cursor resource, or false of not var i: integer; j: integer; iFriendlyType: string; iResourceExtractor: TIEResourceExtractor; iResourceExtractorName: string; begin Result := False; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do begin if i <> 0 then if iFriendlyType = string( iResourceExtractor.FriendlyTypes[ i - 1 ] ) then Break; for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do begin // Use the selection to select the resource iResourceExtractorName := string( iResourceExtractor.Names[ i, j ] ); if iResourceExtractorName = ASelection then begin iFriendlyType := string( iResourceExtractor.FriendlyTypes[ i ] ); Break; end; end; end; Result := iFriendlyType = 'Cursor'; end; finally iResourceExtractor.Free; end; end; function IsResourceBitmap( APath: string; ASelection: string ): boolean; // Returns True if ASelection is a Bitmap resource, or false of not var i: integer; j: integer; iFriendlyType: string; iResourceExtractor: TIEResourceExtractor; iResourceExtractorName: string; begin Result := False; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do begin if i <> 0 then if iFriendlyType = string( iResourceExtractor.FriendlyTypes[ i - 1 ] ) then Break; for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do begin // Use the selection to select the resource iResourceExtractorName := string( iResourceExtractor.Names[ i, j ] ); if iResourceExtractorName = ASelection then begin iFriendlyType := string( iResourceExtractor.FriendlyTypes[ i ] ); Break; end; end; end; Result := iFriendlyType = 'Bitmap'; end; finally iResourceExtractor.Free; end; end; function IsResourcePNG( APath: string; ASelection: string ): boolean; // Returns True if ASelection is a PNG resource, or false of not var i: integer; j: integer; iFriendlyType: string; iResourceExtractor: TIEResourceExtractor; iResourceExtractorName: string; begin Result := False; iResourceExtractor := TIEResourceExtractor.Create( APath ); try if iResourceExtractor.IsValid then begin for i := 0 to iResourceExtractor.TypesCount - 1 do begin if i <> 0 then if iFriendlyType = string( iResourceExtractor.FriendlyTypes[ i - 1 ] ) then Break; for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do begin // Use the selection to select the resource iResourceExtractorName := string( iResourceExtractor.Names[ i, j ] ); if iResourceExtractorName = ASelection then begin iFriendlyType := string( iResourceExtractor.FriendlyTypes[ i ] ); Break; end; end; end; Result := iFriendlyType = 'PNG'; end; finally iResourceExtractor.Free; end; end; procedure TFormResExtractor.ReadIni( IniFilename: string ); // Initialize variables from ini file var i: integer; iIniFile: TIniFile; iFolder: string; iDestinationFolder: string; iDestinationFolderCount: integer; begin iIniFile := TIniFile.Create( IniFilename ); try with iIniFile do begin Left := ReadInteger( 'Form Main', 'Left', 0 ); Top := ReadInteger( 'Form Main', 'Top', 0 ); Width := ReadInteger( 'Form Main', 'Width', 1079 ); Height := ReadInteger( 'Form Main', 'Height', 654 ); FState := ReadInteger( 'Form Main', 'State', 0 ); WindowState := TWindowState( FState ); // If no window coordinates then set position to poDesktopCenter else poDesigned if ( Left = 0 ) and ( Top = 0 ) then Position := poDesktopCenter else Position := poDesigned; // Position - OwnerFormCenter does not work here so center the splash form on its parent FormSplash.Left := Left + ( Width div 2 ) - ( FormSplash.Width div 2 ); FormSplash.Top := Top + ( Height div 2 ) - ( FormSplash.Height div 2 ); FormSplash.Show; FormSplash.Refresh; FormSplash.Update; FStartupFolder := ReadString( 'Form Main', 'StartupFolder', System32Folder ); iDestinationFolderCount := ReadInteger( 'Form Main', 'DestinationFolderCount', 0 ); iDestinationFolder := IncludeTrailingPathDelimiter( CurrentDrive + ':\Images\Extracted Images' ); FDestinationFolder := ReadString( 'Form Main', 'DestinationFolder', iDestinationFolder ); if not DirectoryExists( iDestinationFolder ) then ForceDirectories( iDestinationFolder ); if not DirectoryExists( FDestinationFolder ) then if DirectoryExists( iDestinationFolder ) then FDestinationFolder := iDestinationFolder; // Fill the DestinationFolderComboBox1 with folders for i := 0 to iDestinationFolderCount - 1 do begin iFolder := ReadString( 'DestinationFolders', Format( '%s%d', [ '', i ] ), '' ); if DirectoryExists( iFolder ) then begin if DestinationFolderComboBox1.Items.IndexOf( iFolder ) = -1 then // if not in the list add it DestinationFolderComboBox1.Items.Append( iFolder ); end; end; if iDestinationFolderCount = 0 then begin if DestinationFolderComboBox1.Items.IndexOf( iDestinationFolder ) = -1 then // if not in the list add it DestinationFolderComboBox1.Items.Append( iDestinationFolder ); DestinationFolderComboBox1.ItemIndex := 0; end; end; finally iIniFile.Free; end; end; procedure TFormResExtractor.WriteIni( IniFilename: string ); // Save parameters to ini file var i: integer; iIniFile: TIniFile; iFolder: string; begin iIniFile := TIniFile.Create( IniFilename ); try with iIniFile do begin WriteInteger( 'Form Main', 'Left', Left ); WriteInteger( 'Form Main', 'Top', Top ); WriteInteger( 'Form Main', 'Width', Width ); WriteInteger( 'Form Main', 'Height', Height ); WriteInteger( 'Form Main', 'State', FState ); WriteString( 'Form Main', 'StartupFolder', FStartupFolder ); WriteInteger( 'Form Main', 'DestinationFolderCount', DestinationFolderComboBox1.Items.Count ); FDestinationFolder := DestinationFolderComboBox1.Items[ DestinationFolderComboBox1.ItemIndex ]; WriteString( 'Form Main', 'DestinationFolder', FDestinationFolder ); EraseSection( 'DestinationFolders' ); // Save the DestinationFolderComboBox1 folders for i := 0 to DestinationFolderComboBox1.Items.Count - 1 do begin iFolder := DestinationFolderComboBox1.Items[ i ]; WriteString( 'DestinationFolders', Format( '%s%d', [ '', i ] ), iFolder ); end; end; finally iIniFile.Free; end; end; procedure TFormResExtractor.Report1Click( Sender: TObject ); // Set the ShellListView ViewStyle to Report begin ShellListView1.ViewStyle := vsReport; end; procedure TFormResExtractor.FormCreate( Sender: TObject ); begin FResourceExtractor := nil; FIniFilename := IncludeTrailingBackslash( LocalAppDataFolder ) + 'ASG\ResourceExtractor\' + 'ResourceExtractor.ini'; ForceDirectories( IncludeTrailingBackslash( LocalAppDataFolder ) + 'ASG\ResourceExtractor' ); ReadIni( FIniFilename ); ImageEnView1.Clear; // View 32-bit bitmaps with alphachannel ImageEnView1.IO.Params.BMP_HandleTransparency := True; ShellTreeView1.HideSelection := False; ShellListView1.HideSelection := False; TreeView1.HideSelection := False; Label3.Hint := 'The root destination folder is the parent folder for all extracted images.' + #10#13 + #10#13 + 'Images will be saved to the following folders: ' + #10#13 + 'Group Icons: ' + IncludeTrailingPathDelimiter( FDestinationFolder ) + 'GROUPICONS' + #10#13 + 'Icons: ' + IncludeTrailingPathDelimiter( FDestinationFolder ) + 'ICONS' + #10#13 + 'Bitmaps: ' + IncludeTrailingPathDelimiter( FDestinationFolder ) + 'BMP' + #10#13 + 'PNG Images: ' + IncludeTrailingPathDelimiter( FDestinationFolder ) + 'PNG'; end; procedure TFormResExtractor.FormDestroy( Sender: TObject ); // Free any created objects begin WriteIni( FIniFilename ); FResourceExtractor.Free; end; procedure TFormResExtractor.FormShow( Sender: TObject ); // Setup the Shell and GUI var iNode: TTreeNode; begin // Many dll's with image resources are found in the System32 folder ShellTreeView1.Path := FStartupFolder; // Default- 'C:\Windows\System32'; iNode := ShellTreeView1.Selected; iNode.MakeVisible; ShellTreeView1.TopItem := iNode; // Sort the ShellListView descending by size ShellListSortAscending := False; ShellListSortColumn := 1; // Size Column // Sorting capability was added to ShellCtrls.pas which is located in the project folder ShellListView1.FolderList.Sort( ShellCompare ); ShellListView1.Invalidate; DestinationFolderComboBox1.ItemIndex := DestinationFolderComboBox1.Items.IndexOf( FDestinationFolder ); DestinationFolderComboBox1.Hint := FDestinationFolder; StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( FDestinationFolder, Canvas, 250 ); end; procedure TFormResExtractor.Icon1Click( Sender: TObject ); // Set the ShellListView ViewStyle to Icon begin ShellListView1.ViewStyle := vsIcon; end; procedure TFormResExtractor.ImageEnView1FinishWork( Sender: TObject ); begin Gauge1.Progress := 0; end; procedure TFormResExtractor.ImageEnView1Progress( Sender: TObject; per: integer ); begin Gauge1.MaxValue := 100; Gauge1.Progress := per; end; procedure TFormResExtractor.List1Click( Sender: TObject ); // Set the ShellListView ViewStyle to List begin ShellListView1.ViewStyle := vsList; end; procedure TFormResExtractor.SaveSelectedGroupIcon1Click( Sender: TObject ); // Save the selected group icon to a multi-frame icon var i: integer; j: integer; k: integer; iCurrentDrive: string; iBaseFolder: string; iResFileName: string; iResFileExtension: string; iResourceExtractor: TIEResourceExtractor; iResourceName: string; iFrames: array of TObject; iBuffer: Pointer; iBufferLen: integer; iFileToSave: string; iGroupFrameWidth: integer; iGroupFrameHeight: integer; begin // Create a folder to save the icons to iCurrentDrive := CurrentDrive; iResFileName := ShellListView1.SelectedFolder.PathName; iBaseFolder := IncludeTrailingPathDelimiter( iCurrentDrive + ':\Images\Extracted Images' + JustName( iResFileName ) + '\' ); if DirectoryExists( iBaseFolder ) then SavePictureDialog1.InitialDir := iBaseFolder; SavePictureDialog1.DefaultExt := GraphicExtension( TIcon ); SavePictureDialog1.Filter := GraphicFilter( TIcon ); if SavePictureDialog1.Execute then begin FDestinationFolder := ExcludeTrailingPathDelimiter( ExtractFileDir( SavePictureDialog1.fileName ) ); iResFileExtension := LowerCase( ExtractFileExt( iResFileName ) ); // Is the selected file a resource file if IsFileAResource( iResFileName ) then begin Screen.Cursor := crHourGlass; try iResourceExtractor := TIEResourceExtractor.Create( iResFileName ); try if iResourceExtractor.IsValid then begin // search for GroupIcon, loop among Types for i := 0 to iResourceExtractor.TypesCount - 1 do if iResourceExtractor.FriendlyTypes[ i ] = 'GroupIcon' then begin // GroupIcon found, loop among Names for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do begin iResourceName := string( iResourceExtractor.Names[ i, j ] ); if Assigned( TreeView1.Selected ) then begin // Use selected group icon if iResourceName = 'INTRESOURCE:' + IntToStr( TreeView1.Selected.Index ) then begin // Allocate array of TImageEnView objects and load frames SetLength( iFrames, iResourceExtractor.GroupCountFrames[ i, j ] ); for k := 0 to Length( iFrames ) - 1 do begin iBuffer := iResourceExtractor.GetFrameBuffer( i, j, k, iBufferLen ); iFrames[ k ] := TImageEnView.Create( nil ); iGroupFrameWidth := iResourceExtractor.GroupFrameWidth[ i, j, k ]; iGroupFrameHeight := iResourceExtractor.GroupFrameHeight[ i, j, k ]; ( iFrames[ k ] as TImageEnView ) .IO.Params.IsResource := True; ( iFrames[ k ] as TImageEnView ) .IO.LoadFromBuffer( iBuffer, iBufferLen, ioICO ); ( iFrames[ k ] as TImageEnView ) .IO.Params.ICO_Sizes[ k ].cx := iGroupFrameWidth; ( iFrames[ k ] as TImageEnView ) .IO.Params.ICO_Sizes[ k ].cY := iGroupFrameHeight; ( iFrames[ k ] as TImageEnView ) .IO.Params.ICO_BitCount[ k ] := ( iFrames[ k ] as TImageEnView ).IO.Params.SamplesPerPixel * ( iFrames[ k ] as TImageEnView ).IO.Params.BitsPerSample; end; // Create Multiframe ICO StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( FDestinationFolder, Canvas, 250 ); iFileToSave := SavePictureDialog1.fileName; IEWriteICOImages( iFileToSave, iFrames ); // Cleanup Frames for k := 0 to Length( iFrames ) - 1 do iFrames[ k ].Free( ); end; end; end; end; end; finally iResourceExtractor.Free; end; finally Screen.Cursor := crDefault; end; end; end; end; procedure TFormResExtractor.SaveGroupIcons1Click( Sender: TObject ); // Save all group icons to multi-frame group icons var i: integer; j: integer; k: integer; iResourceExtractor: TIEResourceExtractor; iResFileName: string; iResFileExtension: string; iFrames: array of TObject; iBuffer: Pointer; iBufferLen: integer; iFilePath: string; iResFilePath: string; iBaseFolder: string; iGroupIconFolder: string; iCurrentDrive: string; iResourceName: string; iNumberOfGroupIcons: integer; iPosition: integer; begin iCurrentDrive := CurrentDrive; iFilePath := ShellListView1.SelectedFolder.PathName; if DirectoryExists( FDestinationFolder ) then iBaseFolder := IncludeTrailingPathDelimiter( FDestinationFolder ) else iBaseFolder := IncludeTrailingPathDelimiter( iCurrentDrive + ':\Images\Extracted Images' ); if not DirectoryExists( iBaseFolder ) then if FileCtrl.ForceDirectories( iBaseFolder ) then begin FDestinationFolder := iBaseFolder; StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( FDestinationFolder, Canvas, 250 ); end else begin // Get the folder to save images to iBaseFolder := BrowseForFolder( DesktopFolder ); if DirectoryExists( iBaseFolder ) then begin FDestinationFolder := iBaseFolder; StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( FDestinationFolder, Canvas, 250 ); end else Exit; end; if Assigned( ShellListView1.Selected ) then begin iResFilePath := ShellListView1.SelectedFolder.PathName; iResFileName := ExtractFilename( iResFilePath ); iResFileExtension := LowerCase( ExtractFileExt( iResFileName ) ); // Is the selected file a resource file if IsFileAResource( iResFileName ) then begin Screen.Cursor := crHourGlass; try // Create the GROUPICON folders if ResourceHasGroupIcons( iResFilePath ) then begin iGroupIconFolder := IncludeTrailingPathDelimiter( iBaseFolder ) + 'GROUPICONS\' + JustName( iFilePath ) + '\'; if not DirectoryExists( iGroupIconFolder ) then FileCtrl.ForceDirectories( iGroupIconFolder ); end; iResourceExtractor := TIEResourceExtractor.Create( iResFileName ); try if iResourceExtractor.IsValid then begin iNumberOfGroupIcons := NumberOfGroupIconsInRes( iResFilePath ); Gauge1.MaxValue := iNumberOfGroupIcons; iPosition := 0; Gauge1.Progress := iPosition; // Search for ResType, loop among Types for i := 0 to iResourceExtractor.TypesCount - 1 do begin if iResourceExtractor.FriendlyTypes[ i ] = 'GroupIcon' then begin // GroupIcon found, loop among Names for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do begin // Allocate array of TImageEnView objects and load frames SetLength( iFrames, iResourceExtractor.GroupCountFrames[ i, j ] ); for k := 0 to Length( iFrames ) - 1 do begin iBuffer := iResourceExtractor.GetFrameBuffer( i, j, k, iBufferLen ); iFrames[ k ] := TImageEnView.Create( nil ); ( iFrames[ k ] as TImageEnView ) .IO.Params.IsResource := True; ( iFrames[ k ] as TImageEnView ) .IO.LoadFromBuffer( iBuffer, iBufferLen, ioICO ); end; iResourceName := iGroupIconFolder + CapFirst( JustName( iFilePath ) ) + '_GroupIcon_' + IntToStr ( j + 1 ) + '.ico'; // Save Multiframe ICO IEWriteICOImages( iResourceName, iFrames ); StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( iGroupIconFolder, Canvas, 250 ); inc( iPosition ); Gauge1.Progress := iPosition; if iNumberOfGroupIcons < 20 then Sleep( 50 ); Application.ProcessMessages; // Cleanup Frames for k := 0 to Length( iFrames ) - 1 do iFrames[ k ].Free( ); end; end; end; Gauge1.Progress := 0; end; finally iResourceExtractor.Free; end; finally Screen.Cursor := crDefault; StatusBar1.Panels[ 10 ].Text := ''; ShellListView1.SetFocus; end; end; end; end; procedure TFormResExtractor.Exit1Click( Sender: TObject ); begin Close; end; procedure TFormResExtractor.SaveAs1Click( Sender: TObject ); // Extract the selected resource to a file var iJustResExtension: string; iExtension: string; iFriendlyType: string; iFilePath: string; iResFileName: string; iResExtension: string; iFolder: string; iFileType: integer; iResFilePath: string; begin if Assigned( TreeView1.Selected ) then begin iFolder := IncludeTrailingPathDelimiter( FDestinationFolder ); if Assigned( ShellListView1.Selected ) then begin iResFilePath := ShellListView1.SelectedFolder.PathName; iResFileName := UpperCase( JustName( iResFilePath ) ); iExtension := IEFileTypeToExtension( ImageEnView1.IO.Params.FileType ); iResExtension := ExtractFileExt( iResFilePath ); iJustResExtension := UpperCase( RemoveDotFromExtension( iResExtension ) ); iFileType := ImageEnView1.IO.Params.FileType; if iFileType = ioCUR then begin // Show cursor warning- ImageEN can not save cursors} TaskDialog1.Title := 'Warning'; TaskDialog1.Caption := 'Extracting A Cursor Is Not Supported'; TaskDialog1.Text := 'Saving cursor files is not supported.'; TaskDialog1.CommonButtons := [ tcbOk ]; TaskDialog1.MainIcon := tdiWarning; TaskDialog1.Flags := [ ]; TaskDialog1.Execute; Exit; end; case iFileType of ioICO: iFriendlyType := 'Icon ' + IntToStr( TreeView1.Selected.Index + 1 ); ioBMP: iFriendlyType := 'Bitmap ' + IntToStr( TreeView1.Selected.Index + 1 ); ioPNG: iFriendlyType := 'PNG ' + IntToStr( TreeView1.Selected.Index + 1 ); end; if ( TreeView1.Selected.Parent.Text = 'Icon' ) or ( TreeView1.Selected.Parent.Text = 'Bitmap' ) or ( TreeView1.Selected.Parent.Text = 'PNG' ) then iFilePath := iFolder + TreeView1.Selected.Text + iExtension else // Selection is a GroupIcon iFilePath := iFolder + TreeView1.Selected.Parent.Text + ' ' + TreeView1.Selected.Text + iExtension; SavePictureDialog1.InitialDir := iFolder; SavePictureDialog1.fileName := ExtractFilename( iFilePath ); if SavePictureDialog1.Execute then begin Screen.Cursor := crHourGlass; try iExtension := LowerCase( ExtractFileExt( SavePictureDialog1.fileName ) ); // Save the icon if iExtension = '.ico' then begin ImageEnView1.IO.Params.ICO_Sizes[ 0 ].cx := ImageEnView1.IEBitmap.Width; ImageEnView1.IO.Params.ICO_Sizes[ 0 ].cY := ImageEnView1.IEBitmap.Height; ImageEnView1.IO.Params.ICO_BitCount[ 0 ] := ImageEnView1.IO.Params.BitsPerSample * ImageEnView1.IO.Params.SamplesPerPixel; ImageEnView1.IO.SaveToFile( SavePictureDialog1.fileName, ioICO ); end else if iExtension = '.cur' then begin TaskDialog1.Title := 'Warning'; TaskDialog1.Caption := 'Extracting A Cursor Is Not Supported'; TaskDialog1.Text := 'Saving cursor files is not supported.'; TaskDialog1.CommonButtons := [ tcbOk ]; TaskDialog1.MainIcon := tdiWarning; TaskDialog1.Flags := [ ]; TaskDialog1.Execute; end else // if not icon then do IOPreviews begin ImageEnView1.IO.PreviewsParams := [ ioppDefaultLockPreview ]; if ImageEnView1.IO.DoPreviews( [ ppAUTO ] ) then ImageEnView1.IO.SaveToFile( SavePictureDialog1.fileName ); end; finally Screen.Cursor := crDefault; end; end; ShellListView1.SetFocus; end; end; end; procedure TFormResExtractor.ExtractAll1Click( Sender: TObject ); // Save all images in the resource including group icons var i: integer; j: integer; k: integer; iResourceExtractor: TIEResourceExtractor; iImageEnView: TImageEnView; iResFileName: string; iResFileExtension: string; iFrames: array of TObject; iBuffer: Pointer; iBufferLen: integer; iFilePath: string; iResFilePath: string; iBitmapFolder: string; iPNGFolder: string; iBaseFolder: string; iIconFolder: string; iGroupIconFolder: string; iCurrentDrive: string; iResourceName: string; iWidth: integer; iHeight: integer; iIconPath: string; iNumberOfImagesInRes: integer; iNumberOfBitmaps: integer; iNumberOfPNG: integer; iNumberOfGroupIcons: integer; iNumberOfIcons: integer; begin iCurrentDrive := CurrentDrive; iFilePath := ShellListView1.SelectedFolder.PathName; if DirectoryExists( FDestinationFolder ) then iBaseFolder := IncludeTrailingPathDelimiter( FDestinationFolder ) else iBaseFolder := IncludeTrailingPathDelimiter( iCurrentDrive + ':\Images\Extracted Images' ); if not DirectoryExists( iBaseFolder ) then if FileCtrl.ForceDirectories( iBaseFolder ) then begin FDestinationFolder := IncludeTrailingPathDelimiter( iBaseFolder ); StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( FDestinationFolder, Canvas, 250 ); end else begin // Get the folder to save images to iBaseFolder := IncludeTrailingPathDelimiter( BrowseForFolder( DesktopFolder ) ); if DirectoryExists( iBaseFolder ) then begin FDestinationFolder := IncludeTrailingPathDelimiter( iBaseFolder ); StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( FDestinationFolder, Canvas, 250 ); end else Exit; end; if Assigned( ShellListView1.Selected ) then begin iResFilePath := ShellListView1.SelectedFolder.PathName; iResFileName := ExtractFilename( iResFilePath ); iResFileExtension := LowerCase( ExtractFileExt( iResFileName ) ); // Is the selected file a resource file if IsFileAResource( iResFileName ) then begin Screen.Cursor := crHourGlass; try // Create the BMP, PNG, ICON and GROUPICON folders if ResourceHasBMP( iResFilePath ) then begin iBitmapFolder := IncludeTrailingPathDelimiter( iBaseFolder ) + 'BMP\' + JustName( iFilePath ) + '\'; if not DirectoryExists( iBitmapFolder ) then FileCtrl.ForceDirectories( iBitmapFolder ); end; if ResourceHasPNG( iResFilePath ) then begin iPNGFolder := IncludeTrailingPathDelimiter( iBaseFolder ) + 'PNG\' + JustName( iFilePath ) + '\'; if not DirectoryExists( iPNGFolder ) then FileCtrl.ForceDirectories( iPNGFolder ); end; if ResourceHasIcons( iResFilePath ) then begin iIconFolder := IncludeTrailingPathDelimiter( iBaseFolder ) + 'ICONS\' + JustName( iFilePath ) + '\'; if not DirectoryExists( iIconFolder ) then FileCtrl.ForceDirectories( iIconFolder ); end; if ResourceHasGroupIcons( iResFilePath ) then begin iGroupIconFolder := IncludeTrailingPathDelimiter( iBaseFolder ) + 'GROUPICONS\' + JustName( iFilePath ) + '\'; if not DirectoryExists( iGroupIconFolder ) then FileCtrl.ForceDirectories( iGroupIconFolder ); end; iResourceExtractor := TIEResourceExtractor.Create( iResFileName ); try if iResourceExtractor.IsValid then begin iNumberOfBitmaps := NumberOfBitmapsInRes( iResFilePath ); iNumberOfPNG := NumberOfPNGInRes( iResFilePath ); iNumberOfGroupIcons := NumberOfGroupIconsInRes( iResFilePath ); iNumberOfIcons := NumberOfIconsInRes( iResFilePath ); iNumberOfImagesInRes := iNumberOfBitmaps + iNumberOfPNG + iNumberOfGroupIcons + iNumberOfIcons; Gauge1.MaxValue := iNumberOfImagesInRes; Gauge1.Progress := 0; try // Search for ResType, loop among Types for i := 0 to iResourceExtractor.TypesCount - 1 do begin if iResourceExtractor.FriendlyTypes[ i ] = 'Bitmap' then // Bitmap found begin for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do begin iImageEnView := TImageEnView.Create( nil ); try // Get the image buffer iBuffer := iResourceExtractor.GetBuffer( i, j, iBufferLen ); iImageEnView.IO.Params.IsResource := True; iImageEnView.IO.LoadFromBuffer( iBuffer, iBufferLen, ioBMP ); // Save bitmap iWidth := iImageEnView.IEBitmap.Width; iHeight := iImageEnView.IEBitmap.Height; iResourceName := Format( '%s.bmp', [ IncludeTrailingPathDelimiter( iBitmapFolder ) + CapFirst( JustName( iFilePath ) ) + '_' + IntToStr( iWidth ) + 'x' + IntToStr( iHeight ) + '_' + BitDepthToString ( iImageEnView.IO.Params.SamplesPerPixel, iImageEnView.IO.Params.BitsPerSample ) + '_' + IntToStr( j + 1 ) ] ); iImageEnView.IO.SaveToFile( iResourceName ); StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( iBitmapFolder, Canvas, 250 ); Gauge1.Progress := Gauge1.Progress + 1; Application.ProcessMessages; Sleep( 1 ); finally iImageEnView.Free; end; end; end; // PNG found if iResourceExtractor.FriendlyTypes[ i ] = 'PNG' then begin iImageEnView := TImageEnView.Create( nil ); try for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do begin iBuffer := iResourceExtractor.GetBuffer( i, j, iBufferLen ); iImageEnView.IO.Params.IsResource := True; iImageEnView.IO.LoadFromBuffer( iBuffer, iBufferLen, ioPNG ); // Save PNG iWidth := iImageEnView.IEBitmap.Width; iHeight := iImageEnView.IEBitmap.Height; iResourceName := Format( '%s.png', [ IncludeTrailingPathDelimiter( iPNGFolder ) + CapFirst( JustName( iFilePath ) ) + '_' + IntToStr( iWidth ) + 'x' + IntToStr( iHeight ) + '_' + BitDepthToString ( iImageEnView.IO.Params.SamplesPerPixel, iImageEnView.IO.Params.BitsPerSample ) + '_' + IntToStr( j + 1 ) ] ); iImageEnView.IO.SaveToFile( iResourceName ); StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( iPNGFolder, Canvas, 250 ); Gauge1.Progress := Gauge1.Progress + 1; Application.ProcessMessages; Sleep( 1 ); end; finally iImageEnView.Free; end; end; if iResourceExtractor.FriendlyTypes[ i ] = 'Icon' then // Icon found begin iImageEnView := TImageEnView.Create( nil ); try for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do begin iBuffer := iResourceExtractor.GetBuffer( i, j, iBufferLen ); iImageEnView.IO.Params.IsResource := True; iImageEnView.IO.LoadFromBuffer( iBuffer, iBufferLen, ioICO ); iWidth := iImageEnView.IEBitmap.Width; iHeight := iImageEnView.IEBitmap.Height; iIconFolder := IncludeTrailingPathDelimiter( iBaseFolder ) + 'ICONS\' + IncludeTrailingPathDelimiter( JustName( iFilePath ) ) + IntToStr( iWidth ) + 'x' + IntToStr( iHeight ); if not DirectoryExists( iIconFolder ) then FileCtrl.ForceDirectories( iIconFolder ); iIconPath := Format( '%s.ico', [ IncludeTrailingPathDelimiter( iIconFolder ) + CapFirst( JustName( iFilePath ) ) + '_' + IntToStr( iWidth ) + 'x' + IntToStr( iHeight ) + '_' + BitDepthToString ( iImageEnView.IO.Params.SamplesPerPixel, iImageEnView.IO.Params.BitsPerSample ) + '_' + IntToStr( j + 1 ) ] ); iImageEnView.IO.Params.ICO_Sizes[ 0 ].cx := iWidth; iImageEnView.IO.Params.ICO_Sizes[ 0 ].cY := iHeight; iImageEnView.IO.Params.ICO_BitCount[ 0 ] := iImageEnView.IO.Params.SamplesPerPixel * iImageEnView.IO.Params.BitsPerSample; // Save ICO iImageEnView.IO.SaveToFile( iIconPath ); StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( iIconFolder, Canvas, 250 ); Gauge1.Progress := Gauge1.Progress + 1; Application.ProcessMessages; Sleep( 1 ); end; finally iImageEnView.Free; end; end; if iResourceExtractor.FriendlyTypes[ i ] = 'GroupIcon' then begin // GroupIcon found, loop among Names for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do begin // Allocate array of TImageEnView objects and load frames SetLength( iFrames, iResourceExtractor.GroupCountFrames[ i, j ] ); for k := 0 to Length( iFrames ) - 1 do begin iBuffer := iResourceExtractor.GetFrameBuffer( i, j, k, iBufferLen ); iFrames[ k ] := TImageEnView.Create( nil ); ( iFrames[ k ] as TImageEnView ) .IO.Params.IsResource := True; ( iFrames[ k ] as TImageEnView ) .IO.LoadFromBuffer( iBuffer, iBufferLen, ioICO ); end; iResourceName := iGroupIconFolder + CapFirst( JustName( iFilePath ) ) + '_GroupIcon_' + IntToStr ( j + 1 ) + '.ico'; // Save Multiframe ICO IEWriteICOImages( iResourceName, iFrames ); StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( iGroupIconFolder, Canvas, 250 ); Gauge1.Progress := Gauge1.Progress + 1; Application.ProcessMessages; if iNumberOfGroupIcons < 20 then Sleep( 50 ) else Sleep( 1 ); // Cleanup Frames for k := 0 to Length( iFrames ) - 1 do iFrames[ k ].Free( ); end; end; Gauge1.Progress := Gauge1.Progress + 1; Application.ProcessMessages; end; finally Gauge1.Progress := 0; end; end; finally iResourceExtractor.Free; end; finally Screen.Cursor := crDefault; StatusBar1.Panels[ 10 ].Text := ''; ShellListView1.SetFocus; end; end; end; end; procedure TFormResExtractor.Open1Click( Sender: TObject ); // Open a resource file var i, j, k: integer; ip1, ip2, ip3: TTreeNode; iResBookmark: TIEResourceBookmark; iResFilePath: string; iResFileName: string; iResFileExtension: string; iFolder: string; iFilePath: string; iFileName: string; iFileExtension: string; iExtension: string; iTotalRes: integer; iNumImages: integer; iNumberOfBitmaps: integer; iNumberOfPNG: integer; iNumberOfGroupIcons: integer; iNumberOfIcons: integer; iNumberOfGroupCursors: integer; iNumberOfCursors: integer; iFileType: TIOFileType; iResIsImage: boolean; iFriendlyType: string; iResourceHasImages: boolean; iResourceHasIcons: boolean; iHasExtractableImages: boolean; begin if OpenDialog1.Execute and FileExists( OpenDialog1.fileName ) then begin iResFilePath := OpenDialog1.fileName; iResFileName := ExtractFilename( iResFilePath ); iResFileExtension := LowerCase( ExtractFileExt( iResFileName ) ); if Assigned( FResourceExtractor ) then FResourceExtractor.Free; TreeView1.Items.Clear; // Is the selected file a resource file if IsFileAResource( iResFilePath ) then begin Screen.Cursor := crHourGlass; try TreeView1.Items.BeginUpdate; try TreeView1.Items.Clear; ImageEnView1.Clear; Caption := 'Resource Extractor- ' + iResFilePath; StatusBar1.Panels[ 0 ].Text := FileCtrl.MinimizeName( ExtractFileDir( iResFilePath ), Canvas, 150 ); StatusBar1.Panels[ 1 ].Text := ExtractFilename( iResFilePath ); ImageEnView1.LockPaint; try if FileExists( iResFilePath ) then begin FFilePath := iFileName; iFolder := FDestinationFolder; iFileExtension := ExtractFileExt( FFilePath ); iTotalRes := NumberOfResourcesInRes( iResFilePath ); iNumImages := NumberOfImagesInRes( iResFilePath ); iNumberOfBitmaps := NumberOfBitmapsInRes( iResFilePath ); iNumberOfPNG := NumberOfPNGInRes( iResFilePath ); iNumberOfGroupIcons := NumberOfGroupIconsInRes( iResFilePath ); iNumberOfIcons := NumberOfIconsInRes( iResFilePath ); iNumberOfGroupCursors := NumberOfGroupCursorsInRes( iResFilePath ); iNumberOfCursors := NumberOfCursorsInRes( iResFilePath ); NoResources1.Caption := 'Resources: ' + IntegerToString( iTotalRes ); NoImages1.Caption := 'Images: ' + IntegerToString( iNumImages ); NoBitmaps1.Caption := 'Bitmaps: ' + IntegerToString( iNumberOfBitmaps ); NoPNG1.Caption := 'PNG: ' + IntegerToString( iNumberOfPNG ); NoGroupIcons1.Caption := 'Group Icons: ' + IntegerToString( iNumberOfGroupIcons ); NoIcons1.Caption := 'Icons: ' + IntegerToString( iNumberOfIcons ); NoGroupCursors1.Caption := 'Group Cursors: ' + IntegerToString( iNumberOfGroupCursors ); NoCursors1.Caption := 'Cursors: ' + IntegerToString( iNumberOfCursors ); StatusBar1.Panels[ 2 ].Text := 'Resources: ' + IntegerToString( iTotalRes ); StatusBar1.Panels[ 3 ].Text := 'Images: ' + IntegerToString( iNumImages ); StatusBar1.Panels[ 4 ].Text := 'GroupIcons: ' + IntegerToString( iNumberOfGroupIcons ); StatusBar1.Panels[ 5 ].Text := 'Icons: ' + IntegerToString( iNumberOfIcons ); iResourceHasImages := ResourceHasImages( iResFilePath ); iHasExtractableImages := NumberOfExtractableImagesInRes( iResFilePath ) > 0; SaveImageAs1.Enabled := iResourceHasImages; SaveAllImages1.Enabled := iHasExtractableImages; SaveAs1.Enabled := iResourceHasImages; ExtractAll1.Enabled := iHasExtractableImages; SaveGroupIcons1.Enabled := iNumberOfGroupIcons > 0; SaveAllGroupIcons1.Enabled := iNumberOfGroupIcons > 0; iResourceHasIcons := ResourceHasIcons( iResFilePath ); SaveAllIcons1.Enabled := iResourceHasIcons; SaveAllIcons2.Enabled := iResourceHasIcons; if Assigned( FResourceExtractor ) then FResourceExtractor.Free; FResourceExtractor := TIEResourceExtractor.Create( iResFilePath ); if FResourceExtractor.IsValid then for i := 0 to FResourceExtractor.TypesCount - 1 do begin ip1 := TreeView1.Items.Add( nil, string( FResourceExtractor.FriendlyTypes[ i ] ) ); for j := 0 to FResourceExtractor.NamesCount[ i ] - 1 do if FResourceExtractor.IsGroup[ i ] then begin iFriendlyType := string( FResourceExtractor.FriendlyTypes[ i ] ); ip2 := TreeView1.Items.AddChild( ip1, iResFileName + ' ' + string( FResourceExtractor.FriendlyTypes[ i ] ) + ' ' + IntToStr( j + 1 ) { string ( m_ResourceExtractor.Names [ i, j ] ) } ); for k := 0 to FResourceExtractor.GroupCountFrames[ i, j ] - 1 do begin ip3 := TreeView1.Items.AddChildObject( ip2, IntToStr( FResourceExtractor.GroupFrameWidth[ i, j, k ] ) + ' x ' + IntToStr ( FResourceExtractor.GroupFrameHeight[ i, j, k ] ) + ' ' + IntToStr ( FResourceExtractor.GroupFrameDepth[ i, j, k ] ) + '-bit', FResourceExtractor.GetResourceBookmark( i, j, k ) ); iResBookmark := TIEResourceBookmark( ip3.Data ); iFileType := ioUnknown; if ( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'GroupIcon' ) or ( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'Icon' ) then iFileType := ioICO else if ( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'GroupCursor' ) or ( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'Cursor' ) then iFileType := ioCUR else if ( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'Bitmap' ) then iFileType := ioBMP else if ( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'PNG' ) then iFileType := ioPNG else if ( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'IMAGE' ) then iFileType := ioBMP; iResIsImage := ( iFileType = ioICO ) or ( iFileType = ioCUR ) or ( iFileType = ioBMP ) or ( iFileType = ioPNG ); if iResIsImage then begin iExtension := IEFileTypeToExtension( iFileType ); iFilePath := IncludeTrailingPathDelimiter( iFolder ) + JustName( FFilePath ) + '_' + RemoveDotFromExtension( iFileExtension ) + '_' + IntToStr( i ) + iExtension; end else ImageEnView1.Clear; ImageEnView1.Update; end; end else begin iFileType := ioUnknown; if ( FResourceExtractor.FriendlyTypes[ i ] = 'GroupIcon' ) or ( FResourceExtractor.FriendlyTypes[ i ] = 'Icon' ) then iFileType := ioICO else if ( FResourceExtractor.FriendlyTypes[ i ] = 'GroupCursor' ) or ( FResourceExtractor.FriendlyTypes[ i ] = 'Cursor' ) then iFileType := ioCUR else if ( FResourceExtractor.FriendlyTypes[ i ] = 'Bitmap' ) then iFileType := ioBMP else if ( FResourceExtractor.FriendlyTypes[ i ] = 'PNG' ) then iFileType := ioPNG else if ( FResourceExtractor.FriendlyTypes[ i ] = 'Image' ) then iFileType := ioBMP; iResIsImage := ( iFileType = ioICO ) or ( iFileType = ioCUR ) or ( iFileType = ioBMP ) or ( iFileType = ioPNG ); if iResIsImage then begin TreeView1.Items.AddChildObject( ip1, iResFileName + ' ' + string( FResourceExtractor.FriendlyTypes[ i ] ) + ' ' + IntToStr ( j + 1 ), FResourceExtractor.GetResourceBookmark( i, j ) ); end; end; end; end; finally ImageEnView1.UnLockPaint; end; finally Screen.Cursor := crDefault; end; finally TreeView1.Items.EndUpdate; end; end; end; end; procedure TFormResExtractor.PopupMenu1Popup( Sender: TObject ); // Resource Tree Popupmenu var iFileName: string; iResourceHasImages: boolean; iResourceHasGroups: boolean; iHasExtractableImages: boolean; begin if Assigned( ShellListView1.Selected ) then begin iFileName := ShellListView1.SelectedFolder.PathName; iResourceHasImages := ResourceHasImages( iFileName ); iResourceHasGroups := DoesResourceContainGroupIcon( iFileName ) or DoesResourceContainGroupCursor( iFileName ); iHasExtractableImages := NumberOfExtractableImagesInRes( iFileName ) > 0; SaveImageAs1.Enabled := iResourceHasImages; SaveAllImages1.Enabled := iHasExtractableImages; SaveAs1.Enabled := iResourceHasImages; ExtractAll1.Enabled := iHasExtractableImages; SaveSelectedIimage1.Enabled := iResourceHasImages; SaveAllImagesToAFolder1.Enabled := iHasExtractableImages; SaveAllGroupIconsToMultiframeIconfile1.Enabled := iResourceHasGroups; SaveSelectedGroupIconToMultiFrameIcon1.Enabled := ( iResourceHasGroups ) and ( Assigned( TreeView1.Selected ) ) and ( IsResourceGroupIcon( iFileName, TreeView1.Selected.Index ) ); end; end; procedure TFormResExtractor.ReturnToTheSystem32Folder1Click( Sender: TObject ); // Set the ShellTreeView path to system32 folder begin ShellTreeView1.Path := System32Folder; // Sort the ShellListView descending by size ShellListSortAscending := False; ShellListSortColumn := 1; // Size Column // Sorting capability was added to ShellCtrls.pas which is located in the project folder ShellListView1.FolderList.Sort( ShellCompare ); ShellListView1.Invalidate; end; procedure TFormResExtractor.SaveAllIcons1Click( Sender: TObject ); // Save all icons in resource file ( Does not save any group icons ) var i: integer; j: integer; iResourceExtractor: TIEResourceExtractor; iImageEnView: TImageEnView; iResFileName: string; iResFileExtension: string; iBuffer: Pointer; iBufferLen: integer; iFilePath: string; iPath: string; iBaseFolder: string; iIconFolder: string; iCurrentDrive: string; iWidth: integer; iHeight: integer; iIconPath: string; begin iCurrentDrive := CurrentDrive; iFilePath := ShellListView1.SelectedFolder.PathName; if DirectoryExists( FDestinationFolder ) then iBaseFolder := IncludeTrailingPathDelimiter( FDestinationFolder ) else iBaseFolder := IncludeTrailingPathDelimiter( iCurrentDrive + ':\Images\Extracted Images\ICONS' ) + CapFirst ( JustName( iFilePath ) ); if not DirectoryExists( iBaseFolder ) then if FileCtrl.ForceDirectories( iBaseFolder ) then begin FDestinationFolder := iBaseFolder; StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( FDestinationFolder, Canvas, 250 ); end else begin // Get the folder to save images to iBaseFolder := IncludeTrailingPathDelimiter( BrowseForFolder( DesktopFolder ) ); if DirectoryExists( iBaseFolder ) then begin FDestinationFolder := iBaseFolder; StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( FDestinationFolder, Canvas, 250 ); end else Exit; end; if Assigned( ShellListView1.Selected ) then begin iPath := ShellListView1.SelectedFolder.PathName; iResFileName := ExtractFilename( iPath ); iResFileExtension := LowerCase( ExtractFileExt( iResFileName ) ); // Is the selected file a resource file if IsFileAResource( iResFileName ) then begin Screen.Cursor := crHourGlass; try iResourceExtractor := TIEResourceExtractor.Create( iResFileName ); try if iResourceExtractor.IsValid then begin Gauge1.MaxValue := NumberOfIconsInRes( iResFileName ); Gauge1.Progress := 0; try // Search for ResType, loop among Types for i := 0 to iResourceExtractor.TypesCount - 1 do begin if iResourceExtractor.FriendlyTypes[ i ] = 'Icon' then // Icon found begin iImageEnView := TImageEnView.Create( nil ); try for j := 0 to iResourceExtractor.NamesCount[ i ] - 1 do begin iBuffer := iResourceExtractor.GetBuffer( i, j, iBufferLen ); iImageEnView.IO.Params.IsResource := True; iImageEnView.IO.LoadFromBuffer( iBuffer, iBufferLen, ioICO ); iWidth := iImageEnView.IEBitmap.Width; iHeight := iImageEnView.IEBitmap.Height; iIconFolder := IncludeTrailingPathDelimiter( iBaseFolder ) + 'ICONS\' + IncludeTrailingPathDelimiter( JustName( iFilePath ) ) + IntToStr( iWidth ) + 'x' + IntToStr( iHeight ); if not DirectoryExists( iIconFolder ) then FileCtrl.ForceDirectories( iIconFolder ); iIconPath := Format( '%s.ico', [ IncludeTrailingPathDelimiter( iIconFolder ) + CapFirst( JustName( iFilePath ) ) + '_' + IntToStr( iWidth ) + 'x' + IntToStr( iHeight ) + '_' + BitDepthToString ( iImageEnView.IO.Params.SamplesPerPixel, iImageEnView.IO.Params.BitsPerSample ) + '_' + IntToStr( j + 1 ) ] ); iImageEnView.IO.Params.ICO_Sizes[ 0 ].cx := iWidth; iImageEnView.IO.Params.ICO_Sizes[ 0 ].cY := iHeight; iImageEnView.IO.Params.ICO_BitCount[ 0 ] := iImageEnView.IO.Params.SamplesPerPixel * iImageEnView.IO.Params.BitsPerSample; // Save ICO iImageEnView.IO.SaveToFile( iIconPath ); Gauge1.Progress := Gauge1.Progress + 1; Application.ProcessMessages; Sleep( 1 ); end; finally iImageEnView.Free; end; end; end; finally Gauge1.Progress := 0; end; end; ShellListView1.SetFocus; finally iResourceExtractor.Free; end; finally Screen.Cursor := crDefault; end; end; end; end; procedure TFormResExtractor.About1Click( Sender: TObject ); begin FormAbout := TFormAbout.Create( self ); try FormAbout.ShowModal; finally FormAbout.Free; end; end; procedure TFormResExtractor.BrowseForFolder1Click( Sender: TObject ); // Set the default destination folder with BrowseForFolder var iPath: string; begin if DirectoryExists( FDestinationFolder ) then iPath := BrowseForFolder( FDestinationFolder ) else iPath := BrowseForFolder( DocumentsFolder ); if DirectoryExists( iPath ) then begin FDestinationFolder := iPath; if DestinationFolderComboBox1.Items.IndexOf( iPath ) = -1 then // not in the list begin DestinationFolderComboBox1.Items.Add( FDestinationFolder ); DestinationFolderComboBox1.ItemIndex := DestinationFolderComboBox1.Items.Count - 1; DestinationFolderComboBox1.Hint := FDestinationFolder; end; end; StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( FDestinationFolder, Canvas, 250 ); end; procedure TFormResExtractor.Clear1Click( Sender: TObject ); // Clear all items in the destination combobox begin DestinationFolderComboBox1.Clear; FDestinationFolder := ''; end; procedure TFormResExtractor.DefaultDestinationFolder1Click( Sender: TObject ); // Set the default destination folder var iPath: string; begin if DirectoryExists( FDestinationFolder ) then iPath := BrowseForFolder( FDestinationFolder ) else iPath := BrowseForFolder( DocumentsFolder ); if DirectoryExists( iPath ) then begin FDestinationFolder := iPath; if DestinationFolderComboBox1.Items.IndexOf( iPath ) = -1 then // not in the list begin DestinationFolderComboBox1.Items.Add( FDestinationFolder ); DestinationFolderComboBox1.ItemIndex := DestinationFolderComboBox1.Items.Count - 1; DestinationFolderComboBox1.Hint := FDestinationFolder; end; end; StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( FDestinationFolder, Canvas, 250 ); end; procedure TFormResExtractor.Delete1Click( Sender: TObject ); // Remove the selected destination folder from the combobox begin DestinationFolderComboBox1.Items.delete( DestinationFolderComboBox1.ItemIndex ); end; procedure TFormResExtractor.DestinationFolder1Click( Sender: TObject ); // Set the destination folder begin FDestinationFolder := BrowseForFolder( FDestinationFolder ); StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( FDestinationFolder, Canvas, 250 ); end; procedure TFormResExtractor.DestinationFolderComboBox1CloseUp( Sender: TObject ); // Set the destination folder begin FDestinationFolder := DestinationFolderComboBox1.Items[ DestinationFolderComboBox1.ItemIndex ]; DestinationFolderComboBox1.Hint := FDestinationFolder; StatusBar1.Panels[ 10 ].Text := FileCtrl.MinimizeName( FDestinationFolder, Canvas, 250 ); Label3.Hint := 'The root destination folder is the parent folder for all extracted images.' + #10#13 + #10#13 + 'Images will be saved to the following folders: ' + #10#13 + 'Group Icons: ' + IncludeTrailingPathDelimiter( FDestinationFolder ) + 'GROUPICONS' + #10#13 + 'Icons: ' + IncludeTrailingPathDelimiter( FDestinationFolder ) + 'ICONS' + #10#13 + 'Bitmaps: ' + IncludeTrailingPathDelimiter( FDestinationFolder ) + 'BMP' + #10#13 + 'PNG Images: ' + IncludeTrailingPathDelimiter( FDestinationFolder ) + 'PNG'; end; procedure TFormResExtractor.Zoom1Change( Sender: TObject ); // Change ImageENView zoom const iZoomVal: array [ 0 .. 6 ] of double = ( 0, 25, 50, 100, 200, 400, 800 ); begin if Zoom1.ItemIndex = 0 then begin ImageEnView1.AutoFit := True; ImageEnView1.Update; end else begin ImageEnView1.AutoFit := False; ImageEnView1.Zoom := iZoomVal[ Zoom1.ItemIndex ]; end; end; procedure TFormResExtractor.TreeView1Change( Sender: TObject; Node: TTreeNode ); // Respond to Treeview changes var iResBookmark: TIEResourceBookmark; iBuffer: Pointer; iBufferLen: integer; iFileType: TIOFileType; iDimensions: string; iSmallDimensions: string; iBitDepth: integer; iColors: string; iResIsImage: boolean; iFriendlyType: string; iResFileName: string; iResourceHasImages: boolean; iResourceHasGroups: boolean; iResourceHasIcons: boolean; iHasExtractableImages: boolean; begin if not Node.HasChildren and Assigned( Node.Data ) then begin iResBookmark := TIEResourceBookmark( Node.Data ); iBuffer := FResourceExtractor.GetBuffer( iResBookmark, iBufferLen ); if FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'GroupIcon' then SaveSelectedGroupIcon1.Enabled := True; // Set the file type iFriendlyType := string( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] ); iFileType := ioUnknown; if ( iFriendlyType = 'GroupIcon' ) or ( iFriendlyType = 'Icon' ) then iFileType := ioICO else if ( iFriendlyType = 'GroupCursor' ) or ( iFriendlyType = 'Cursor' ) then iFileType := ioCUR else if ( iFriendlyType = 'Bitmap' ) then iFileType := ioBMP else if ( iFriendlyType = 'PNG' ) then iFileType := ioPNG; if Assigned( ShellListView1.Selected ) then begin iResFileName := ShellListView1.SelectedFolder.PathName; iResourceHasGroups := DoesResourceContainGroupIcon( iResFileName ) or DoesResourceContainGroupCursor ( iResFileName ); iHasExtractableImages := NumberOfExtractableImagesInRes( iResFileName ) > 0; SaveAllImages1.Enabled := iHasExtractableImages; ExtractAll1.Enabled := iHasExtractableImages; if iFriendlyType = 'GroupIcon' then begin SaveGroupIcons1.Enabled := iResourceHasGroups; SaveSelectedGroupIcon1.Enabled := True; SaveAllGroupIcons1.Enabled := iResourceHasGroups; SaveAllGroupIconsToMultiframeIconfile1.Enabled := iResourceHasGroups; SaveSelectedGroupIcon2.Enabled := True; SaveSelectedGroupIconToMultiFrameIcon1.Enabled := True; end; if iFileType = ioICO then begin SaveAs1.Enabled := True; SaveImageAs1.Enabled := True; SaveGroupIcons1.Enabled := iResourceHasGroups; if TreeView1.Selected.Parent.Text = 'GroupIcon' then SaveSelectedGroupIcon1.Enabled := True; SaveAllGroupIcons1.Enabled := iResourceHasGroups; SaveAllGroupIconsToMultiframeIconfile1.Enabled := iResourceHasGroups; SaveSelectedGroupIcon2.Enabled := True; SaveSelectedGroupIconToMultiFrameIcon1.Enabled := True; StatusBar1.Panels[ 6 ].Text := 'Icon'; end else if iFileType = ioCUR then begin SaveAs1.Enabled := False; SaveImageAs1.Enabled := False; SaveGroupIcons1.Enabled := iResourceHasGroups; SaveSelectedGroupIcon1.Enabled := False; SaveAllGroupIcons1.Enabled := iResourceHasGroups; SaveAllGroupIconsToMultiframeIconfile1.Enabled := iResourceHasGroups; SaveSelectedGroupIcon2.Enabled := False; SaveSelectedGroupIconToMultiFrameIcon1.Enabled := False; StatusBar1.Panels[ 6 ].Text := 'Cursor'; end else if iFileType = ioBMP then begin SaveAs1.Enabled := True; SaveImageAs1.Enabled := True; SaveGroupIcons1.Enabled := iResourceHasGroups; SaveSelectedGroupIcon1.Enabled := False; SaveAllGroupIcons1.Enabled := iResourceHasGroups; SaveAllGroupIconsToMultiframeIconfile1.Enabled := iResourceHasGroups; SaveSelectedGroupIcon2.Enabled := False; SaveSelectedGroupIconToMultiFrameIcon1.Enabled := False; StatusBar1.Panels[ 6 ].Text := 'Bitmap'; end else if iFileType = ioPNG then begin SaveAs1.Enabled := True; SaveImageAs1.Enabled := True; SaveGroupIcons1.Enabled := iResourceHasGroups; SaveSelectedGroupIcon1.Enabled := False; SaveAllGroupIcons1.Enabled := iResourceHasGroups; SaveAllGroupIconsToMultiframeIconfile1.Enabled := iResourceHasGroups; SaveSelectedGroupIcon2.Enabled := False; SaveSelectedGroupIconToMultiFrameIcon1.Enabled := False; StatusBar1.Panels[ 6 ].Text := 'PNG'; end else begin SaveAs1.Enabled := False; SaveImageAs1.Enabled := False; SaveGroupIcons1.Enabled := iResourceHasGroups; SaveSelectedGroupIcon1.Enabled := False; SaveAllGroupIcons1.Enabled := iResourceHasGroups; SaveAllGroupIconsToMultiframeIconfile1.Enabled := iResourceHasGroups; SaveSelectedGroupIcon2.Enabled := False; SaveSelectedGroupIconToMultiFrameIcon1.Enabled := False; StatusBar1.Panels[ 6 ].Text := ''; end; iResIsImage := ( iFileType = ioICO ) or ( iFileType = ioCUR ) or ( iFileType = ioBMP ) or ( iFileType = ioPNG ); if iResIsImage then begin ImageEnView1.IO.Params.IsResource := True; ImageEnView1.IO.LoadFromBuffer( iBuffer, iBufferLen, iFileType ); ImageEnView1.IO.Params.FileType := iFileType; end else ImageEnView1.Blank; ImageEnView1.Update; iDimensions := IntegerToString( ImageEnView1.IEBitmap.Width ) + ' pixels x ' + IntegerToString ( ImageEnView1.IEBitmap.Height ) + ' pixels'; iSmallDimensions := IntegerToString( ImageEnView1.IEBitmap.Width ) + ' x ' + IntegerToString ( ImageEnView1.IEBitmap.Height ); iBitDepth := ImageEnView1.IO.Params.BitsPerSample * ImageEnView1.IO.Params.SamplesPerPixel; if iBitDepth = 32 then begin ImageEnView1.Background := clBtnFace; ImageEnView1.BackgroundStyle := iebsChessboard; ImageEnView1.SetChessboardStyle( 4 ); iColors := 'RGBA ' + IntToStr( iBitDepth ) + ' bit'; end else begin ImageEnView1.Background := clWindow; ImageEnView1.BackgroundStyle := iebsSolid; iColors := 'RGB ' + IntToStr( iBitDepth ) + ' bit'; end; if iFriendlyType = 'GroupIcon' then Frames1.Caption := 'Frames: ' + IntegerToString( NodeChildCount( TreeView1.Selected.Parent ) ) else Frames1.Caption := 'Frames: 1'; Dimensions1.Caption := 'Dimensions: ' + iSmallDimensions; Colors1.Caption := 'Colors: ' + iColors; StatusBar1.Panels[ 7 ].Text := 'Frames: ' + IntegerToString( NodeChildCount( TreeView1.Selected.Parent ) ); StatusBar1.Panels[ 8 ].Text := iDimensions; StatusBar1.Panels[ 9 ].Text := iColors; end; end else begin Node.Expand( False ); if Assigned( ShellListView1.Selected ) then iResFileName := ShellListView1.SelectedFolder.PathName; iResourceHasGroups := DoesResourceContainGroupIcon( iResFileName ) or DoesResourceContainGroupCursor ( iResFileName ); iResourceHasImages := ResourceHasImages( iResFileName ); iResourceHasIcons := ResourceHasIcons( iResFileName ); ImageEnView1.Blank; SaveAs1.Enabled := ( TreeView1.Selected.Text <> 'GroupCursor' ) and ( TreeView1.Selected.Text <> 'Cursor' ) and ( TreeView1.Selected.Text <> 'Image' ) and ( TreeView1.Selected.Text <> 'GroupIcon' ); SaveImageAs1.Enabled := ( TreeView1.Selected.Text <> 'GroupCursor' ) and ( TreeView1.Selected.Text <> 'Cursor' ) and ( TreeView1.Selected.Text <> 'Image' ) and ( TreeView1.Selected.Text <> 'GroupIcon' ); ExtractAll1.Enabled := iResourceHasImages; SaveAllIcons1.Enabled := iResourceHasIcons; SaveAllIcons2.Enabled := iResourceHasIcons; if ( TreeView1.Selected.Level = 1 ) and ( TreeView1.Selected.Parent.Text = 'GroupIcon' ) then begin StatusBar1.Panels[ 6 ].Text := 'GroupIcon'; SaveSelectedGroupIcon1.Enabled := True; SaveSelectedGroupIcon2.Enabled := True; end else if ( TreeView1.Selected.Level = 1 ) and ( TreeView1.Selected.Parent.Text = 'GroupCursor' ) then begin SaveAs1.Enabled := False; SaveImageAs1.Enabled := False; StatusBar1.Panels[ 6 ].Text := 'GroupCursor'; end else begin SaveAs1.Enabled := ( TreeView1.Selected.Text <> 'GroupIcon' ) and ( TreeView1.Selected.Text = 'Icon' ) and ( TreeView1.Selected.Text <> 'GroupCursor' ) and ( TreeView1.Selected.Text = 'Cursor' ) and ( TreeView1.Selected.Text = 'Bitmap' ) and ( TreeView1.Selected.Text = 'PNG' ) and ( TreeView1.Selected.Text <> 'Image' ); SaveImageAs1.Enabled := ( TreeView1.Selected.Text <> 'GroupIcon' ) and ( TreeView1.Selected.Text = 'Icon' ) and ( TreeView1.Selected.Text <> 'GroupCursor' ) and ( TreeView1.Selected.Text = 'Cursor' ) and ( TreeView1.Selected.Text = 'Bitmap' ) and ( TreeView1.Selected.Text = 'PNG' ) and ( TreeView1.Selected.Text <> 'Image' ); SaveGroupIcons1.Enabled := iResourceHasGroups; SaveAllGroupIcons1.Enabled := iResourceHasGroups; SaveSelectedGroupIcon1.Enabled := False; SaveSelectedGroupIcon2.Enabled := False; StatusBar1.Panels[ 6 ].Text := TreeView1.Selected.Text; StatusBar1.Panels[ 7 ].Text := ''; StatusBar1.Panels[ 8 ].Text := ''; StatusBar1.Panels[ 9 ].Text := ''; end; if TreeView1.Selected.Level = 0 then begin Frames1.Caption := 'Frames:'; StatusBar1.Panels[ 7 ].Text := ''; end; if ( TreeView1.Selected.Level > 0 ) and ( TreeView1.Selected.Parent.Text = 'GroupIcon' ) then begin Frames1.Caption := 'Frames: ' + IntegerToString( CountChildNodes( TreeView1 ) ); Dimensions1.Caption := 'Dimensions:'; Colors1.Caption := 'Colors:'; StatusBar1.Panels[ 7 ].Text := 'Frames: ' + IntegerToString( CountChildNodes( TreeView1 ) ); end else begin Frames1.Caption := 'Frames:'; Dimensions1.Caption := 'Dimensions:'; Colors1.Caption := 'Colors:'; StatusBar1.Panels[ 7 ].Text := ''; end; end; end; procedure TFormResExtractor.TreeView1GetImageIndex( Sender: TObject; Node: TTreeNode ); // Get the image index of the selected node begin if Node.HasChildren then begin if Node.Expanded then Node.ImageIndex := 0 else Node.ImageIndex := 1; Node.SelectedIndex := 1; end else begin Node.ImageIndex := 2; Node.SelectedIndex := 2; end; end; procedure TFormResExtractor.ViewIcons1Click( Sender: TObject ); // Icon viewer var iCurrentDrive: string; iFilePath: string; iBaseFolder: string; iTreeNode: TTreeNode; begin FormViewIcons := TFormViewIcons.Create( self ); try if Assigned( ShellListView1.Selected ) then begin iCurrentDrive := CurrentDrive; iFilePath := ShellListView1.SelectedFolder.PathName; iBaseFolder := IncludeTrailingPathDelimiter( iCurrentDrive + ':\Images\Extracted Images\GROUPICONS' ) + CapFirst ( JustName( iFilePath ) ); if DirectoryExists( iBaseFolder ) then begin // Set the icon viewer path to match the selected resource file FormViewIcons.ShellTreeView1.Path := iBaseFolder; iTreeNode := FormViewIcons.ShellTreeView1.Selected; if Assigned( iTreeNode ) then begin // For some reason the listview does not change when the treeview path is set, so force a change by changing the treeview nodes FormViewIcons.ShellTreeView1.Selected := FormViewIcons.ShellTreeView1.Items.Item [ FormViewIcons.ShellTreeView1.Selected.Index + 1 ]; FormViewIcons.ShellTreeView1.Selected := iTreeNode; // Make the node visible iTreeNode.MakeVisible; // Make the node the top node FormViewIcons.ShellTreeView1.TopItem := iTreeNode; end; end; end; FormViewIcons.ShowModal; finally FormViewIcons.Free; end; end; procedure TFormResExtractor.Saveimageas1Click( Sender: TObject ); // Save image as... begin if SavePictureDialog1.Execute then ImageEnView1.IO.SaveToFile( SavePictureDialog1.fileName ); end; procedure TFormResExtractor.SavePictureDialog1TypeChange( Sender: TObject ); // Change the SavePictureDialog file extension when the filter changes var FilePath: string; fileName: string; FileExt: string; begin FilePath := SavePictureDialog1.fileName; FileExt := ExtractFileExt( FilePath ); fileName := ExtractFilename( FilePath ); end; procedure TFormResExtractor.ShellListView1Change( Sender: TObject; Item: TListItem; Change: TItemChange ); // Respond to ShellListView changes var i, j, k: integer; ip1, ip2, ip3: TTreeNode; iResBookmark: TIEResourceBookmark; iResFilePath: string; iResFileName: string; iResFileExtension: string; iResFileShortExtension: string; iFolder: string; iFilePath: string; iFileName: string; iFileExtension: string; iExtension: string; iShortExtension: string; iTotalRes: integer; iNumImages: integer; iNumberOfBitmaps: integer; iNumberOfPNG: integer; iNumberOfGroupIcons: integer; iNumberOfIcons: integer; iNumberOfGroupCursors: integer; iNumberOfCursors: integer; iFileType: TIOFileType; iResIsImage: boolean; iFriendlyType: string; iResourceHasIcons: boolean; iHasExtractableImages: boolean; begin if Assigned( ShellListView1.Selected ) then begin iResFilePath := ShellListView1.SelectedFolder.PathName; iResFileName := JustName( iResFilePath ); iResFileExtension := LowerCase( ExtractFileExt( iResFileName ) ); iResFileShortExtension := RemoveDotFromExtension( UpperCase( ExtractFileExt( iResFilePath ) ) ); // Is the selected file a resource file if IsFileAResource( iResFilePath ) then begin Screen.Cursor := crHourGlass; try TreeView1.Items.BeginUpdate; try TreeView1.Items.Clear; ImageEnView1.Clear; Caption := 'Resource Extractor- ' + iResFilePath; StatusBar1.Panels[ 0 ].Text := FileCtrl.MinimizeName( ExtractFileDir( iResFilePath ), Canvas, 150 ); StatusBar1.Panels[ 1 ].Text := ExtractFilename( iResFilePath ); ImageEnView1.LockPaint; try if FileExists( iResFilePath ) then begin FFilePath := iFileName; iFolder := FDestinationFolder; iFileExtension := ExtractFileExt( FFilePath ); iTotalRes := NumberOfResourcesInRes( iResFilePath ); iNumImages := NumberOfImagesInRes( iResFilePath ); iNumberOfBitmaps := NumberOfBitmapsInRes( iResFilePath ); iNumberOfPNG := NumberOfPNGInRes( iResFilePath ); iNumberOfGroupIcons := NumberOfGroupIconsInRes( iResFilePath ); iNumberOfIcons := NumberOfIconsInRes( iResFilePath ); iNumberOfGroupCursors := NumberOfGroupCursorsInRes( iResFilePath ); iNumberOfCursors := NumberOfCursorsInRes( iResFilePath ); NoResources1.Caption := 'Resources: ' + IntegerToString( iTotalRes ); NoImages1.Caption := 'Images: ' + IntegerToString( iNumImages ); NoBitmaps1.Caption := 'Bitmaps: ' + IntegerToString( iNumberOfBitmaps ); NoPNG1.Caption := 'PNG: ' + IntegerToString( iNumberOfPNG ); NoGroupIcons1.Caption := 'Group Icons: ' + IntegerToString( iNumberOfGroupIcons ); NoIcons1.Caption := 'Icons: ' + IntegerToString( iNumberOfIcons ); NoGroupCursors1.Caption := 'Group Cursors: ' + IntegerToString( iNumberOfGroupCursors ); NoCursors1.Caption := 'Cursors: ' + IntegerToString( iNumberOfCursors ); StatusBar1.Panels[ 2 ].Text := FormatByteSize( FileSize( iResFilePath ) ); StatusBar1.Panels[ 3 ].Text := 'Resources: ' + IntegerToString( iTotalRes ); StatusBar1.Panels[ 4 ].Text := 'Images: ' + IntegerToString( iNumImages ); StatusBar1.Panels[ 5 ].Text := 'GroupIcons: ' + IntegerToString( iNumberOfGroupIcons ); StatusBar1.Panels[ 6 ].Text := 'Icons: ' + IntegerToString( iNumberOfIcons ); iHasExtractableImages := NumberOfExtractableImagesInRes( iResFilePath ) > 0; SaveImageAs1.Enabled := iHasExtractableImages; SaveAllImages1.Enabled := iHasExtractableImages; SaveAs1.Enabled := iHasExtractableImages; ExtractAll1.Enabled := iHasExtractableImages; SaveGroupIcons1.Enabled := iNumberOfGroupIcons > 0; SaveAllGroupIcons1.Enabled := iNumberOfGroupIcons > 0; iResourceHasIcons := ResourceHasIcons( iResFilePath ); SaveAllIcons1.Enabled := iResourceHasIcons; SaveAllIcons2.Enabled := iResourceHasIcons; if Assigned( FResourceExtractor ) then FResourceExtractor.Free; FResourceExtractor := TIEResourceExtractor.Create( iResFilePath ); if FResourceExtractor.IsValid then for i := 0 to FResourceExtractor.TypesCount - 1 do begin ip1 := TreeView1.Items.Add( nil, string( FResourceExtractor.FriendlyTypes[ i ] ) ); for j := 0 to FResourceExtractor.NamesCount[ i ] - 1 do if FResourceExtractor.IsGroup[ i ] then begin iFriendlyType := string( FResourceExtractor.FriendlyTypes[ i ] ); if ( iFriendlyType = 'GroupIcon' ) or ( iFriendlyType = 'Icon' ) then iShortExtension := 'Icon' else if ( iFriendlyType = 'GroupCursor' ) or ( iFriendlyType = 'Cursor' ) then iShortExtension := 'Cursor' else if ( iFriendlyType = 'Bitmap' ) then iShortExtension := 'Bitmap' else if ( iFriendlyType = 'PNG' ) then iShortExtension := 'Png' else iShortExtension := ''; iResFileName := JustName( iResFilePath ); ip2 := TreeView1.Items.AddChild( ip1, CapFirst( iResFileName ) + iResFileShortExtension + ' ' + string ( FResourceExtractor.FriendlyTypes[ i ] ) + ' ' + iShortExtension + ' ' + IntToStr( j + 1 ) ); for k := 0 to FResourceExtractor.GroupCountFrames[ i, j ] - 1 do begin ip3 := TreeView1.Items.AddChildObject( ip2, IntToStr( FResourceExtractor.GroupFrameWidth[ i, j, k ] ) + ' x ' + IntToStr ( FResourceExtractor.GroupFrameHeight[ i, j, k ] ) + ' ' + IntToStr ( FResourceExtractor.GroupFrameDepth[ i, j, k ] ) + '-bit', FResourceExtractor.GetResourceBookmark( i, j, k ) ); iResBookmark := TIEResourceBookmark( ip3.Data ); iFileType := ioUnknown; if ( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'GroupIcon' ) or ( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'Icon' ) then iFileType := ioICO else if ( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'GroupCursor' ) or ( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'Cursor' ) then iFileType := ioCUR else if ( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'Bitmap' ) then iFileType := ioBMP else if ( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'PNG' ) then iFileType := ioPNG else if ( FResourceExtractor.FriendlyTypes[ iResBookmark.TypeIndex ] = 'IMAGE' ) then iFileType := ioBMP; iResIsImage := ( iFileType = ioICO ) or ( iFileType = ioCUR ) or ( iFileType = ioBMP ) or ( iFileType = ioPNG ); if iResIsImage then begin iExtension := IEFileTypeToExtension( iFileType ); iFilePath := IncludeTrailingPathDelimiter( iFolder ) + JustName( FFilePath ) + '_' + RemoveDotFromExtension( iFileExtension ) + '_' + IntToStr( i ) + iExtension; end else ImageEnView1.Clear; ImageEnView1.Update; end; end else begin iFileType := ioUnknown; if ( FResourceExtractor.FriendlyTypes[ i ] = 'GroupIcon' ) or ( FResourceExtractor.FriendlyTypes[ i ] = 'Icon' ) then iFileType := ioICO else if ( FResourceExtractor.FriendlyTypes[ i ] = 'GroupCursor' ) or ( FResourceExtractor.FriendlyTypes[ i ] = 'Cursor' ) then iFileType := ioCUR else if ( FResourceExtractor.FriendlyTypes[ i ] = 'Bitmap' ) then iFileType := ioBMP else if ( FResourceExtractor.FriendlyTypes[ i ] = 'PNG' ) then iFileType := ioPNG else if ( FResourceExtractor.FriendlyTypes[ i ] = 'Image' ) then iFileType := ioBMP; iResFileName := JustName( iResFilePath ) + iShortExtension; iResIsImage := ( iFileType = ioICO ) or ( iFileType = ioCUR ) or ( iFileType = ioBMP ) or ( iFileType = ioPNG ); if iResIsImage then begin TreeView1.Items.AddChildObject( ip1, CapFirst( iResFileName ) + iResFileShortExtension + ' ' + string ( FResourceExtractor.FriendlyTypes[ i ] ) + ' ' + IntToStr( j + 1 ), FResourceExtractor.GetResourceBookmark( i, j ) ); end; end; end; end; finally ImageEnView1.UnLockPaint; end; finally Screen.Cursor := crDefault; end; finally TreeView1.Items.EndUpdate; end; end else begin StatusBar1.Panels[ 2 ].Text := ''; StatusBar1.Panels[ 3 ].Text := 'Resources: 0'; StatusBar1.Panels[ 4 ].Text := ''; StatusBar1.Panels[ 5 ].Text := ''; StatusBar1.Panels[ 6 ].Text := ''; end; end; end; procedure TFormResExtractor.ShellListView1ColumnClick( Sender: TObject; Column: TListColumn ); // Respond to ShellListViewcolumn click - requires modified shellctrls.pas located in the application folder begin ShellListSortColumn := Column.Index; ShellListSortAscending := not ShellListSortAscending; ShellListView1.FolderList.Sort( ShellCompare ); ShellListView1.Invalidate; end; procedure TFormResExtractor.ShellListView1KeyDown( Sender: TObject; var Key: Word; Shift: TShiftState ); // Respond to Shelllistview keydown var iResFilePath: string; iResFileName: string; iResFileExtension: string; iNumImages: integer; iTotalRes: integer; iNumberOfBitmaps: integer; iNumberOfPNG: integer; iNumberOfGroupIcons: integer; iNumberOfIcons: integer; iNumberOfGroupCursors: integer; iNumberOfCursors: integer; iHasExtractableImages: boolean; begin if Assigned( ShellListView1.Selected ) then begin iResFilePath := ShellListView1.SelectedFolder.PathName; iResFileName := ExtractFilename( iResFilePath ); iResFileExtension := LowerCase( ExtractFileExt( iResFileName ) ); // Is the selected file a resource file if IsFileAResource( iResFilePath ) then begin iTotalRes := NumberOfResourcesInRes( iResFilePath ); iNumImages := NumberOfImagesInRes( iResFilePath ); iNumberOfBitmaps := NumberOfBitmapsInRes( iResFilePath ); iNumberOfPNG := NumberOfPNGInRes( iResFilePath ); iNumberOfGroupIcons := NumberOfGroupIconsInRes( iResFilePath ); iNumberOfIcons := NumberOfIconsInRes( iResFilePath ); iNumberOfGroupCursors := NumberOfGroupCursorsInRes( iResFilePath ); iNumberOfCursors := NumberOfCursorsInRes( iResFilePath ); FileName1.Caption := 'Filename: ' + iResFilePath; FileSize1.Caption := 'Filesize: ' + FormatByteSize( FileSize( iResFilePath ) ); NoResources1.Caption := 'Resources: ' + IntegerToString( iTotalRes ); NoImages1.Caption := 'Images: ' + IntegerToString( iNumImages ); NoBitmaps1.Caption := 'Bitmaps: ' + IntegerToString( iNumberOfBitmaps ); NoPNG1.Caption := 'PNG: ' + IntegerToString( iNumberOfPNG ); NoGroupIcons1.Caption := 'Group Icons: ' + IntegerToString( iNumberOfGroupIcons ); NoIcons1.Caption := 'Icons: ' + IntegerToString( iNumberOfIcons ); NoGroupCursors1.Caption := 'Group Cursors: ' + IntegerToString( iNumberOfGroupCursors ); NoCursors1.Caption := 'Cursors: ' + IntegerToString( iNumberOfCursors ); StatusBar1.Panels[ 2 ].Text := FormatByteSize( FileSize( iResFilePath ) ); StatusBar1.Panels[ 3 ].Text := 'Resources: ' + IntegerToString( iTotalRes ); StatusBar1.Panels[ 4 ].Text := 'Images: ' + IntegerToString( iNumImages ); StatusBar1.Panels[ 5 ].Text := 'GroupIcons: ' + IntegerToString( iNumberOfGroupIcons ); StatusBar1.Panels[ 6 ].Text := 'Icons: ' + IntegerToString( iNumberOfIcons ); iHasExtractableImages := NumberOfExtractableImagesInRes( iResFilePath ) > 0; SaveImageAs1.Enabled := iHasExtractableImages; SaveAllImages1.Enabled := iHasExtractableImages; SaveAs1.Enabled := iHasExtractableImages; ExtractAll1.Enabled := iHasExtractableImages; SaveGroupIcons1.Enabled := iNumberOfGroupIcons > 0; SaveAllGroupIcons1.Enabled := iNumberOfGroupIcons > 0; end; end; end; procedure TFormResExtractor.ShellListView1MouseDown( Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer ); // Respond to shelllistview mousedown var iResFilePath: string; iResFileName: string; iResFileExtension: string; iNumImages: integer; iTotalRes: integer; iNumberOfBitmaps: integer; iNumberOfPNG: integer; iNumberOfGroupIcons: integer; iNumberOfIcons: integer; iNumberOfGroupCursors: integer; iNumberOfCursors: integer; iHasExtractableImages: boolean; begin if Assigned( ShellListView1.Selected ) then begin iResFilePath := ShellListView1.SelectedFolder.PathName; iResFileName := ExtractFilename( iResFilePath ); iResFileExtension := LowerCase( ExtractFileExt( iResFileName ) ); // Is the selected file a resource file if IsFileAResource( iResFilePath ) then begin iTotalRes := NumberOfResourcesInRes( iResFilePath ); iNumImages := NumberOfImagesInRes( iResFilePath ); iNumberOfBitmaps := NumberOfBitmapsInRes( iResFilePath ); iNumberOfPNG := NumberOfPNGInRes( iResFilePath ); iNumberOfGroupIcons := NumberOfGroupIconsInRes( iResFilePath ); iNumberOfIcons := NumberOfIconsInRes( iResFilePath ); iNumberOfGroupCursors := NumberOfGroupCursorsInRes( iResFilePath ); iNumberOfCursors := NumberOfCursorsInRes( iResFilePath ); FileName1.Caption := 'Filename: ' + iResFilePath; FileSize1.Caption := 'Filesize: ' + FormatByteSize( FileSize( iResFilePath ) ); NoResources1.Caption := 'Resources: ' + IntegerToString( iTotalRes ); NoImages1.Caption := 'Images: ' + IntegerToString( iNumImages ); NoBitmaps1.Caption := 'Bitmaps: ' + IntegerToString( iNumberOfBitmaps ); NoPNG1.Caption := 'PNG: ' + IntegerToString( iNumberOfPNG ); NoGroupIcons1.Caption := 'Group Icons: ' + IntegerToString( iNumberOfGroupIcons ); NoIcons1.Caption := 'Icons: ' + IntegerToString( iNumberOfIcons ); NoGroupCursors1.Caption := 'Group Cursors: ' + IntegerToString( iNumberOfGroupCursors ); NoCursors1.Caption := 'Cursors: ' + IntegerToString( iNumberOfCursors ); StatusBar1.Panels[ 2 ].Text := FormatByteSize( FileSize( iResFilePath ) ); StatusBar1.Panels[ 3 ].Text := 'Resources: ' + IntegerToString( iTotalRes ); StatusBar1.Panels[ 4 ].Text := 'Images: ' + IntegerToString( iNumImages ); StatusBar1.Panels[ 5 ].Text := 'GroupIcons: ' + IntegerToString( iNumberOfGroupIcons ); StatusBar1.Panels[ 6 ].Text := 'Icons: ' + IntegerToString( iNumberOfIcons ); iHasExtractableImages := NumberOfExtractableImagesInRes( iResFilePath ) > 0; SaveImageAs1.Enabled := iHasExtractableImages; SaveAllImages1.Enabled := iHasExtractableImages; SaveAs1.Enabled := iHasExtractableImages; ExtractAll1.Enabled := iHasExtractableImages; SaveGroupIcons1.Enabled := iNumberOfGroupIcons > 0; SaveAllGroupIcons1.Enabled := iNumberOfGroupIcons > 0; end; end; end; procedure TFormResExtractor.ShellTreeView1Change( Sender: TObject; Node: TTreeNode ); // Respond to shelltreeview change var iPath: string; begin if Assigned( ShellTreeView1.Selected ) then begin iPath := ShellTreeView1.SelectedFolder.PathName; FStartupFolder := iPath; Caption := 'Resource Extractor- ' + iPath; StatusBar1.Panels[ 0 ].Text := FileCtrl.MinimizeName( iPath, Canvas, 150 ); end; end; procedure TFormResExtractor.SmallIcon1Click( Sender: TObject ); // Set the shelllistview viewstyle to smallicon begin ShellListView1.ViewStyle := vsSmallIcon; end; end.