diff --git a/Example.dpr b/Example.dpr new file mode 100644 index 0000000..9102765 --- /dev/null +++ b/Example.dpr @@ -0,0 +1,18 @@ +program Example; + +uses + Vcl.Forms, + ExampleUnit in 'ExampleUnit.pas' {ExampleForm1}, + Winapi.FileThumbnail in 'Winapi.FileThumbnail.pas'; + +{$R *.res} + +begin + {$IFDEF DEBUG} + ReportMemoryLeaksOnShutdown := True; + {$ENDIF} + Application.Initialize; + Application.MainFormOnTaskbar := True; + Application.CreateForm(TExampleForm1, ExampleForm1); + Application.Run; +end. diff --git a/Example.dproj b/Example.dproj new file mode 100644 index 0000000..43fcd75 --- /dev/null +++ b/Example.dproj @@ -0,0 +1,967 @@ + + + {13F2E426-C03F-4649-A043-70F506A81FA0} + 19.5 + VCL + True + Release + Win32 + 1 + Application + Example.dpr + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + .\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) + $(BDS)\bin\delphi_PROJECTICON.ico + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png + Example + + + JvNet;vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;TreeListViewPackage;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;JvBands;inetdb;JPPack;JvAppFrm;FireDACSqliteDriver;DbxClientDriver;GR32_R;FireDACASADriver;Tee;soapmidas;JclVcl;vclactnband;TeeUI;fmxFireDAC;dbexpress;Jcl;JvManagedThreads;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;JvPascalInterpreter;vcltouch;fmxase;JvPluginSystem;DBXOdbcDriver;JvDB;dbrtl;JvTimeFramework;FireDACDBXDriver;FireDACOracleDriver;CodeSiteExpressPkg;fmxdae;TeeDB;FireDACMSAccDriver;JvCustom;CustomIPTransport;FireDACMSSQLDriver;JvSystem;DataSnapIndy10ServerTransport;JclDeveloperTools;JvControls;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;JvCrypt;FireDACMongoDBDriver;JvJans;JvMM;IndySystem;JvWizards;FireDACTDataDriver;JvGlobus;vcldb;JclContainers;JvPageComps;PngComponents;vclFireDAC;JvCore;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;JPLib;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;JvDotNetCtrls;JvHMI;DBXSybaseASEDriver;IGDIPlusMod;JvRuntimeDesign;DBXDb2Driver;JvXPCtrls;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;JvStdCtrls;JvDlgs;JvDocking;JvPrintPreview;bindcompvcl;dsnap;GR32_D;JvCmp;SearchBarPackage;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;FMXTee;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + 1033 + $(BDS)\bin\default_app.manifest + + + vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;JPPack;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;FireDACOracleDriver;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;vcldb;PngComponents;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;JPLib;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;FMXTee;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) + + + DEBUG;$(DCC_Define) + true + false + true + true + true + true + true + + + false + PerMonitorV2 + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + PerMonitorV2 + + + + MainSource + + +
ExampleForm1
+ dfm +
+ + + Base + + + Cfg_1 + Base + + + Cfg_2 + Base + +
+ + Delphi.Personality.12 + Application + + + + Example.dpr + + + + + + Example.exe + true + + + + + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + classes + 64 + + + classes + 64 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + Contents\MacOS + 1 + .framework + + + Contents\MacOS + 1 + .framework + + + Contents\MacOS + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + Contents\Resources\StartUp\ + 0 + + + Contents\Resources\StartUp\ + 0 + + + Contents\Resources\StartUp\ + 0 + + + 0 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + ..\ + 1 + + + ..\ + 1 + + + ..\ + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).launchscreen + 64 + + + ..\$(PROJECTNAME).launchscreen + 64 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + ..\ + 1 + + + ..\ + 1 + + + ..\ + 1 + + + + + Contents + 1 + + + Contents + 1 + + + Contents + 1 + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + Contents\MacOS + 1 + + + Contents\MacOS + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + + + + + + + + + + + + True + False + + + 12 + + + + +
diff --git a/Example.res b/Example.res new file mode 100644 index 0000000..0e4c269 Binary files /dev/null and b/Example.res differ diff --git a/ExampleUnit.dfm b/ExampleUnit.dfm new file mode 100644 index 0000000..6a75e0e --- /dev/null +++ b/ExampleUnit.dfm @@ -0,0 +1,785 @@ +object ExampleForm1: TExampleForm1 + Left = 0 + Top = 0 + Caption = 'ExampleForm1' + ClientHeight = 300 + ClientWidth = 569 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -12 + Font.Name = 'Segoe UI' + Font.Style = [] + KeyPreview = True + OnCreate = FormCreate + OnShow = FormShow + DesignSize = ( + 569 + 300) + TextHeight = 15 + object Image1: TImage + Left = 8 + Top = 37 + Width = 256 + Height = 256 + end + object JvFilenameEdit1: TJvFilenameEdit + Left = 8 + Top = 8 + Width = 553 + Height = 23 + Anchors = [akLeft, akTop, akRight] + TabOrder = 0 + Text = 'JvFilenameEdit1' + ExplicitWidth = 549 + end + object Panel1: TPanel + Left = 433 + Top = 153 + Width = 128 + Height = 128 + Anchors = [akTop, akRight] + BevelInner = bvRaised + BevelOuter = bvLowered + Caption = 'Panel1' + ShowCaption = False + TabOrder = 2 + ExplicitLeft = 429 + object Image2: TImage + Left = 2 + Top = 2 + Width = 124 + Height = 124 + Hint = 'Drag a file here to quickly set file paths and extract icons.' + Align = alClient + Center = True + ParentShowHint = False + Picture.Data = { + 0954506E67496D61676589504E470D0A1A0A0000000D49484452000002000000 + 02000806000000F478D4FA000000097048597300004EBD00004EBD01736A6814 + 0000001974455874536F667477617265007777772E696E6B73636170652E6F72 + 679BEE3C1A00004EC54944415478DAEDDD09BC55D3FBC7F1E776BBCDF3A05193 + 068D2A8A26A908199244494A8A0CA1492129943227F4439993F9679E33463214 + 3F6332644828CDF3AD7BFFCF3ABBFE4A75EF39670FEB9CBD3FEF97E775A373D6 + 59EBBAF7ECEFD97BEDB532040000444E86ED0E000080E0110000008820020000 + 0011440000002082080000004410010000800822000000104104000000228800 + 0000400411000000882002000000114400000020820800000044100100008008 + 2200000010410400000022880000004004110000008820020000001144000000 + 2082080000004410010000800822000000104104000000228800000040041100 + 0000882002000000114400000020820800000044100100008008220000001041 + 04000000228800000040041100FC91A555C2651B6BB5B65BEA7F41AD92F4DF6A + FFCDCFD0264BAF0F20020800DE69AB3558ABA3560DAD4C97ED9983CFEF5AAF6A + DDA5F589CFFDEFA03548EB48AD2AE2FE6783FEBBEFFF66ADD55ACBB43ED35AA8 + F5BED6029FFB0220020800EE994FFA776BF5F1F13572B5EED3BA409C838297CC + 27E5995ABDE87FDAF4FF27AD27B5EED5FAD6C77103083102803BE6E0FFA656AB + 805EEF5DADAE5A5B3CECBF69B305FD4FCBFEE7683DA3759DF87F860240C81000 + DC7958AB6FC0AF7987D6851EB5F5A8D669F43FEDFB6FCE5098B308976AAD0AF8 + FB01204D110092D75A6BBE85D735D7A69B697DEDB21D3367E17DFA1FAAFEFFA9 + 3550EB250BDF1700698600903C734D7880A5D7BE516B94CB36CC27C681F43F74 + FD379705AED09A22CE990100D82B0240F27E1667B6BF0D6636784B976D2CD1AA + 49FF43DB7F3341D0DC959213D0F704409A2100242F5B9CFBB56D58A155D1C5F3 + 0B88339B3D8BFE87BAFFD3C5B97381330100F64000488EED0390B9D65BD9C5F3 + CDFF77B3C84C61FA1FFAFE5FAB756510DF1400E9850090BCEFB4EA597A6D33F9 + F030FA4FFFE3603EFD1F2F4C0C04F02F0480E4DDA9759EA5D7BE5AEB2A976D4C + 13EF6E67A3FFA9DDFFBFB50ED25A1AD0EB0148030480E499C55BCCE22B05027E + 5D73E9E140712621BAD1549CC96C6E972CA6FFE9D17F73D7C1A0805E0B401A20 + 00B8631685393FE0D71CAF35C1A3B66ED31A4AFF23D17F3369B592B05010801D + 0800EE14D27A41EBA8805EEF31ADD3C5BB5BBBCC24C6E7B58EA6FF91E8FF295A + 4F05F45A00521C01C03D1302268BF349CEAFDB02CD8C71B3DEFB44F1FEBEEE82 + 3BDABE58FCBBAB81FEDBEDFF4E66F1A21B7D7E0D00698200E09DBAE22CBCD259 + AB9A561197ED6D1467D7B7D7B4EED7FAD5E7FE1F20CECA86663B5AB3C05151FA + 6FB5FF15C409975E1A2B4E880100020090A2CCE4D2AAE2DC6E6826EF995D08DD + FEBE0ED07AC0F6C000A4060200901ECC990173F0AEEAA28DDAE22C410C000400 + 208DD4D2FA509CD9FC899A234E880080180200905ECC2581B724B13926E61640 + B3FDF027B63B0F2075100080F47386389703E25984CA2C053C44EB6EDB9D0690 + 5A0800407A3A49EB3EAD32793C66AD3877A63C6EBBB300520F0100485FE5B42E + D2EAA9D56497FFFEB5D6D35A53C5D9BA1800F64000D89399296DAEB39AED5E57 + 6B2DD69AA7B5DD76C7803C983503CA8AF333BBC5766700A43E02C03F3A89B348 + 4A9BBDFCDD72715650336BB76FB6DD510000DC220038DF03B3B9CB58C9FFFBF1 + 9138D75E97D9EE3400006E10009C03FF35093CFE73AD765A1B6C771C00806445 + 3D00B410E7DEE8786EA7DAD52D5AC36D771E008064453D003CA3D53D89E79949 + 5635B5FEB43D0000009211E50050429CC97DC9EEDA67EEAF9E617B1000002423 + CA01A0953893FA9275A7D605B60701004032A21C008ED37AC1C5F3CD422B3D6D + 0F02008064443900986BFFCFB878FEB3E2DC12080040DA2100248F000000485B + 0480E411000000698B00903C020000206D11009247000000A42D0240F2080000 + 80B44500481E0100A9C62C696D96B7AEA5554C6BA9D67C61DF0A007B4100481E + 0100A9C21CEC2FDA5155FEF57766FBEAA7B4C669FD68BBA30052070120790400 + A4825A5ACF6935CDE771E62C407F71C2000010005C3C9F0000DBCA6B7DA85537 + CEC7E788F373EF66054C00214100481E0100B63DAED52BC1E7AC142730ACB2DD + 7900761100924700804D07692D94E47E87AFD5BAD2F60000D84500481E010036 + 4DD4BA3CC9E77EAF55CFF60000D84500481E010036BDA275B48BE797D65A6B7B + 1000EC2100248F00009BCCE9FFE62E9E7FA0D622DB8300604F9403C0F15ACFBB + 78FED35A3D6D0F0291F585561317CF37B70D7E697B1000EC897200682DCE2A69 + C99AAE75BEED4120B20800005C89720030D740FFD22A94E4F3CDC17FBAED4120 + B20800005CF13B0034D46A27CEF5C6FA5A15C559B6B484ED81EF5079477F1295 + ABF5ABD636DB038820F33D5FA7B5466B89D677E25C0F7F5FA2B5E63D0100802B + 7E0480365A678A33C9AE8ACBB680786D152704CCD27A42C23FC39D0000C015AF + 0240A6382B925DA6D5CCF6A01079E64CC03D5A378AB3235E18110000B8E24500 + E8A07587E4BF19091034B313DEF55A93B536D9EE8CC70800005C7113008A6ADD + A2758ECB7600BFFDA0D557DCDDF5916A0800005C49F6C06D961135DB8AF2A91F + E9225B6B94D654DB1DF1080100802BC9048083B55ED2DACF76E781244CD3BA44 + 9CAD71D3190100802B890680565A73B44ADAEE38E082992078AE38B773A62B02 + 000057120900E65EFEF7B42AD8EE34E081495A57D8EE840B040000AEC41B00CC + C23D1F8B130280B038439C7503D2110100802BF1068087C479B304C2C42C1664 + E6B47C6FBB234920000070259E00708CD6CBB63B0AF8E45DAD2324FDE6031000 + 00B8925F0030F7FA9B37893AB63B0AF8E874ADD9B63B91A0CFC5DDAA9B8DB5BE + B63D0800F6E417002E14E7B62920CCCC4241667E4B3A6DEEF486561717CF3793 + 79FFB63D0800F6E41500B2C4B9365AC3762781009895021FB1DD8904DCA63534 + C9E7FEA15555D2EFB207000FE515004E1667B53F200ACC4E82ED6D7722019DC5 + 5993231977690DB13D000076E51500FEAB7592172F52A8502169D5AA951C74D0 + 4152BE7C792955AA94ED71234D656767CBEAD5ABE5FBEFBF97F9F3E7CBD2A59E + 6DF6673E0D9B25AE7FB03DC604CCD56A97E073CCB6C98DD26C9C007CB0AF0050 + 4C6B955621B72F70E8A1874A9F3E7DA44C9932B6C78A90C9CDCD9579F3E6C9C3 + 0F3F2C1B376EF4A2C9D1E2EC1E982ECC44BE0FB41249D4C3C5D9C40B40C4ED2B + 0074D57AD56DE33D7AF490EEDDBBDB1E2342EE8F3FFE90EBAFBF5E56AE5CE9B6 + 29F3337F8CEDF124E808712ED595CBE771E60C8759FD70ACED0E03480DFB0A00 + D788CB378A0E1D3AC8D9679F6D7B7C88889F7FFE59AEBDF6DAD82502173688F3 + 693ADD360AAA2DCE998B9EB2F7DFE96FB4468AB3891700C4EC2B003CADD523D9 + 468B172F1EFB4466BE024179ECB1C7E4E5975DAF59650EA64B6C8F2549FB6B1D + AB758056112D3341E26D7196F166C63F80DDEC2B0098C57F1A27DBE871C71D27 + BD7AF5B23D3644CCDAB56BE5924B2E919C1C571FE0CD01F415DB630100BFED2B + 002C1717BBFE8D1D3B56EAD6AD6B7B6C88207319C0DC21E0C200AD076C8F0300 + FCB6AF00B059AB70B28DDE71C71D9CFE87153367CE94F7DE7BCF4D1366719DDB + 6D8F0300FCB6B70050406B7BD20D6664C8BDF7DE1BFB0A04EDF1C71F97975E72 + 35D76D8CD614DBE30000BFEDED289D292ED6442F50A0402C0000363CF1C413F2 + E28B2FBA69E232ADC9B6C701007E23002054080000101F02004285000000F121 + 002054080000101F02004285000000F121002054080000101F02004285000000 + F121002054080000101F02004285000000F121002054080000101F0200428500 + 0000F121002054221E00CC3E1E2DB46A6915D35AAA355F6B83ED8E01483D0400 + 844A44038039D85FB4A3AAFCEBEFCCCE9E4F698DD3FAD1764701A40E02004225 + 8201A096D6735A4DF3799C390BD05F9C3000000400844BC4024079AD0FB5EAC6 + F9F81CADEE5A2FD8EE3800FB08000895880580C7B57A25F89C95E2048655B63B + 0FC02E020042254201E020AD85B2F7DFE1FC5CAB75A5ED0100B08B0080508950 + 0098A8757992CFFD5EAB9EED0100B08B0080508950007845EB6817CF2FADB5D6 + F62000D8430040A844280098D3FFCD5D3CFF40AD45B60701C01E020042254201 + E00BAD262E9E6F6E1BFCD2F62000D8430040A81000E2460000228E0080502100 + C48D0000441C0100A14200881B0100883802004285001037020010710400840A + 01206E040020E2080008150240DC080040C41100102A0480B811008088230020 + 5408007123000011470040A81000E2460000228E0080502100C48D0000441C01 + 00A14200881B0100883802004285001037020010710400840A01206E040020E2 + 080008150240DC080040C41100102A110A009F6B3573F1FCC65A5FDB1E04007B + 0800089508058037B4BAB8787E05ADBF6D0F02803D0400844A8402C06D5A4393 + 7CEE1F5A55B5726D0F02803D0400844A84024067AD39493EF72EAD21B60700C0 + 2E020042254201C098ABD52EC1E76CD56AA4F583EDCE03B08B00805089580030 + 13F93ED02A95C073866BDD62BBE300EC230020542216008C23B49ED22A97CFE3 + CCF5FE495A636D7718406A200020542218008CDA5AD76BF594BDFF4E7FA33552 + EB25DB1D05903A080008958806809DF6D73A56EB00AD225A4BB5DED6FA5898F1 + 0FE05F0800089588070000881B0100A1F2DFFFFE579E7DF659374D30490E4024 + 1000102A6FBEF9A63CF8E0836E9AE8ADF598ED710080DF080008955F7EF945C6 + 8D1BE7A60933A16E89ED710080DF0800089DCB2FBF5C7EFFFDF7649EFABE567B + DBFD0780201000103A0B172E94A953A726FA34334BBEA3D67BB6FB0F00412000 + 20941E79E41179EDB5D712798AB96E708DED7E034050080008A5DCDC5C79FAE9 + A7E585175E88FD390FDBB52E1767211D00880C020042EDA79F7E8ADD16F8F9E7 + 9F6FD520506897BFDAA465160C98A0F5A5ED7E0240D008008884EFBEFBAEC5A4 + 4993CCCF7659ADBFB516696DB4DD2F00B085008048C8C8C868D0BF7FFFEF6CF7 + 03005205010009CBC9C99165CB96C91F7FFC11ABBFFFFE5BB66EDD2A5BB66C89 + FD7D565696142A5448CA942923952B57964A952A49B56AD562FFCD16020000EC + 8E0080B8AC58B1423EFEF863F9E69B6F64F1E2C5B269D3A6849E5FB06041A95D + BBB63468D0405AB66C2975EAD409B4FF040000D81D0100FB949D9D2D1F7CF081 + CC9D3B57BEFFFEFBFC66D327C49C1568D3A68D74EEDC594A952AE5FB58080000 + B03B0200F6603EDDCF993327761FFDDAB56B7D7D2D73B9A07DFBF6D2AD5B37A9 + 58B1A26FAF43000080DD1100F0FFCC27FC4F3EF94466CF9E2D2B57AE0CF4B5CD + 25824E9D3A49CF9E3DA54891229EB74F000080DD11001063AEF1DF7DF7DDE676 + 39ABFD285FBEBC0C1A34481A366CE869BB040004CCBC8F9A6B5B25B43688B3EE + 44621367009F1100200B162C90993367CA860D1B6C7725460FD672E491474AEF + DEBD253333D3AB360900F04361AD565A1DB49A69D5DB517B9BD8922DCE4E938B + B5BE1567F3A9B95A7FD91E04A289001061E694FF534F3D155B2E3715356EDC58 + 860E1DEAC9250102003C544CEB44ADD3B58ED42AEAB2BDCFB51ED39A2D6C458D + 00110022CADCCBFFC0030FC83BEFBC63BB2B79AA5EBDBA8C1C3932B6A6801B04 + 0078A086D630ADB3B54AFAD0BEB9CD668ED614AD376C0F16E14700882073F09F + 3E7D7AECBEFE74606E191C3D7AB4942B572EE936080070A18AD644AD33B4B202 + 7ACD055A978A1308005F10002268D6AC59F2FAEBAFDBEE46422A54A82063C68C + 897D4D060100493007FB8BC4D92ADAFFC52AF6EE49AD115ABFD8FE66207C0800 + 11F3FCF3CFC7AEFBA7233767020800489039DDFF88563BDB1D51EBB4CED39A65 + BB2308170240842C5AB448A64C9912BB0490AE923D13400040024ED6326F62A5 + 6D77E45F66680DD5DA6CBB230807024044AC5BB74EC68D1B27AB56ADB2DD15D7 + 9209010400C4C91C606FD52A60BB23FB6066ED76D75A63BB23487F048088B8EB + AEBB64DEBC79B6BBE199444300010071B84E6B8CED4EC4E17F5AC7682DB3DD11 + A43702400498DDFB264D9AE4E9663EA92091104000403E866BDD64BB1309308B + 091DA1F5BBED8E207D110042CE1CF4C78F1F2F3FFFFCB32FED1F54AB9A1CDEF8 + 00D9BF4259A958AA84142A98297FAD59277FAC5E271F2DFE59E67EFDA3646FDF + EEDBF8E29D184800401EEA6B7DA555D0764712645613ECA4F587ED8E203D1100 + 42EEB3CF3E935B6FBDD5D336CD817E44F74E726ABB1652AD7CDE0BF4ACDDB459 + 5EFEF46B99F2DF37E4AB5FFC799F8A27041000529679BF3133EECD691C33E9AE + B8D65671D6CD37D7B97FD55AE1731FEED7EA6FFB1B91A46FC409017FDAEE08D2 + 0F0120E4CCA97FAF36F829929525A37A74918B8FEF28258B164EE8B939B9B932 + FBBD4F65ECAC17E5F795DECF5FCA2F041000524623ADC3B5DA6B1DAC5547AB50 + 3ECF313357CDFF3B3389E55DADF7C4BB50603EF59BB5F8CBDAFEC6B860CE5E74 + 16F6144082080021B664C992D8E97F2FD4AA5A519E9C3C5C9AD5DD5F247B9BE4 + 6ECDD6CF695A9BB698EB0C71B7B362DD06E93FF56179E3F3459E8F37AF104000 + B0CA6C8E73FA8EAAEF417BE69A925921CFDCA7FFB438F7C927EB00ADEF6D7F83 + 3CC0E500248C001062B367CF96575F7DD5753B07D6AA26AF4EBB4CAA54D8DB87 + 243DF86FDC2AB96627C12DD971B567E6049C7DFB6C796CEE02CFC7BCAF104000 + B0C27CCA372BE9F514FF6EAB3307FFFBB46ED0FA2D89E79BB3109F58F9EE78EF + 0B71CE04F87DC9042141000829B3D8CFF0E1C365F5EAD5AEDA3107FDF7674C90 + EA95CAE7FFE02D1A04D6AC77CE0CE463BBF6CF84007359C06B7B0B0104804099 + 6D716FD3EA18E06B6ED19AA675B5247646A096D64F7E74A86066A6542C5B52D6 + ACDF281B376F0DEAFB607616ECA2F577502F88F4450008A91F7EF841AEB9E61A + 576D142890A19FFCAF908E2D1BC6FFA45CFD67C346111304F2B9341064082000 + 04C2EC9037496B88D89B516FEE8D1F29CEE5817864EE784E45B72F5CA75A2539 + BE7D0BE9D6BEA534AE535DF62B5BCAFCDCC5FE6EFDA6CDB2E4F7E5F2FAFC2FE4 + E50F16CADCCF16C936FFEE8EF94C9C10B0D2AF174038100042EAC5175F94279E + 78C2551BBDBBB69507275C90DC93B76D97DC15AB625FF36242C0E03B1E9559EF + 7A7F1676D775020800BE6BA9F5A838D7FB5381D9F06290563CA7C0EED23A27D9 + 176A58BB9A4C38A79774EF78C8FF1FF0F3F3C36F7FCA847B9E94C7DF98273939 + BEACCF61AEAF1D29CE044A60AF08002175CB2DB7C8E79F7F9EF4F3B30A66CAFF + 66DF200754AF947C27CC198015AB25774BDEA73F830801152B562400F8C76C54 + 738B5662B786F8CF4CEEEBA1F5653E8FAB25CE24BA84FA5FA450965C77611F19 + D2F328C92C90DC1487CFBE5B22FDC7DF29DFFCB4D48FF19B536B47092100FB40 + 0008A961C386B95AF7BFCFD1EDE481F1E7BBEF8809017F6B08D89C7F08F0F372 + 4047F5F8E38FBFEB79E3D166DE3FAEDA51A9CA9C0138519C5B07F362CE16DC13 + 6FA315CB9492676F1E258734ACE3BA83667E40DFB1B7C98BEF2FF463FC1F6B75 + 95F8CE842062080021B465CB1619326488ABA57F674FBC487A763ED49B0E693F + 72FF5E23B2794B9E0FF3F34C406666E6D2EDDBB79B59E94B3C6F3C9ACC7BC77F + C4C5A9F3009945854ED37A7E5F0FC8FDEAF142D74E7BF29709F73C5529BF6BF3 + E694FFD3D78F707776EC5FCC6B9E79D59DF2E49C0FFD18FF47E284003610C26E + 080021F4EBAFBFCA95575E99F4F3CDE9FFDF5FFE8F942E51CCBB4E251002FC3A + 1320CE296173AF7432B78BD96026D2B5D06A2ACEB5755366B53CB3FCA2593CC7 + DC6E6166BC6FD0FA519CC572CCA9ECF9E2EEDEF8785CAE35D1F6372801E614D4 + A95ACFEEED2FB33F9C35527F446FF8F8EB1FE4CAE98FC95B9F7EBD478036BF0F + 434F3D46869F719C94285AC4F30E9A1070C6B8DBE5E9373FF263FC26591CADB5 + D68FC6919E080021F4D5575FC90D37DC90F4F3CD279CCF1FB9DEFB8EA5C09900 + 71CE007492D43D1350599C4FABDDB4DA6A9548A20DF3FB6B6682BFA1355B9CDD + E3BC544BCBACE494DF0A7EA9C6042613029ED9F53FE6BE755F91AD45B27ECA90 + 8CCA3BFFDBB215AB6233F597FDBD5A8A17291CFBB4DFB6597D2994E5EFCD0DD9 + DBB64BDF2BA7C9336F7FEC47F36625451302FC0E8748130480105AB06081DC76 + DB6D493FBFF3218DE5956997FBD33942C0DE98DFC3E3B52E14E7F6AD4C8FDB37 + 4BC59AEBDB33B5D67BD09EF9E11A1AE437C8437B9C09D8FAE1AC732437762740 + 4A3021A0CF15B7C973FEFCEC7F20CE56C284001000C268DEBC7972D75DC9BF9F + 9D7A541B79F8EA0BFDEB209703763253C7FB8AB3077DA3005ECFDC177EBB38DB + DEBA39156C2E37D40EA0BF7ED92D046C9D37CB7C323ECC76A776654240EF2BA6 + CAF3EFFAF2B34F08400C012084E6CF9F2FD3A74F4FFAF9271E7E883C396598BF + 9DE44C80B96FDEAC5CD7D6C26B9BF5E2CDCCFD195A39093ED79CF6DF2C7B7FEF + 4827B1CB019BE63FF879664EE60FA9389EADD9DB6221E085F7BC5F325BBD2F4E + 08F0E28C10D214012084DC6E017C6893BAF2DE3D13FCEF6834438039804ED6BA + 58FC5B1F3F5EEF689D21899D05319310C3724BD9D64BCFEC3EE3DAF34EF5E07E + 579F3AA821E0B4CBA7CA8B3EEC9BA1E66A1D2B8480C8220084D0A2458BE4BAEB + AE4BFAF9552B969525CFDD1E4C67A37539A0963893F252E974B3B9356CB056BC + CB469AF70C73D74151AF3A6056CFAB52B654AC2A9529299BB666CB9FABD7C5B6 + 8D5EBD6193AF832F985920E7B149971438E1F0837D7D1D376221E0B25BFD5A27 + C0AC8F60269C120222880010422B56AC90912347BA6AE37FB3AF8FED02188868 + 9C09308B2ABCA815C7AE4A8133F7BB994D74C6C7F9F8D7C559663669E6A07F4C + 8B867242AB26D2EDE046B183FF1E9DD29F8B853F2D95973EFD4A1ED783DFA2A5 + FE6C776F66F6CFBEF622897008300B649910B0C1F638112C0240089937CE73CE + 3947B2B3E3DB9E776F265F78BA0CEF7B5C909D0E730838419C75F23D5C58C117 + 664EC22592FFBC8001E26CC19B94635A369409BDBB49F3DAF1074CF3FF7DF67B + 0BE4EAC75E919F977BBFC74D3A84802DFAFB7CDA6553E5257F42800975DDC559 + 340911410008A9B163C7CA6FBF257F46FBA07A35E5A30726C6BDB98927C27939 + C0ACC5FE92D8DB1D2F51E6C06E96C5CD2B0498B19875061A27D270B952C5E5EE + 4BCF96135A371531E1D46C1BBD2DB11DF1B6E827E1CB1F7E41EE78F93D572B5D + EE4D3A84804D5BB6CAC9A36E92391FE7B7BD41524C0830CB266FB63D4E048300 + 1052F7DD779FBCF3CE3BAEDAF07439E07885EB4C80D962D62C9853D68F4EFA28 + 9E10D0400F980BB6666F8BEBAC468DCA15E4A5A963A47E8D2ABBFFC5F61CC9DD + A4C79BF51B130A03F7BD395F2EB8EB89D8CF8197D22504F41879A3BCF9C9577E + 34FF9A386702080111400008A90F3EF840EEBEFB6E576D9837EB85B3A6C49606 + 0E5478CE04DCA835C2B7EF93BFF20C01B92FBD54F89325F37E3D6DE25D157FCC + E7DA7CBB831AC8A3932E964AE54AE7F9B85CF3FF7BED06E7CC401CCCBC8001B7 + CD8A6408301B08F51875A3BCE54F087855EB242104841E0120A456AE5C292346 + 8C707D9A7454BF1364E2F9BD831F40FA87808C1DCFABEAF7B7CA47F76B9D2D7B + 09015BE7CDBA48BF4C3507A23B9F7C4DEE7DEE2DF9FED73FFE197C4686B46850 + 4B2E3CF5E8D8CE92096D976BCE08AC5A27B9711CD8A31E024E1A7983BCFDE9D7 + 7E34FF8A3821608BDB8690BA0800213671E24459BC78B1AB36CC1BF9DD970F96 + FEC7770C7E00E97D39C06CDCF35D00DF25BFED712620F793BBB2B2B34B987054 + 63D7072EFD6BA5FCF2E70AC92A58506A55A92815CA944CFE55B7EBCBAD5AEB9C + 15C847D44340F711D7CB3B0BBEF1A3F997B57A082120B40800213667CE1C79E8 + A1875CB7632E0198A5817B746A1DFC20D2F74C80D97A38BF3DE8D3C56E2160CB + 078FF4C9C8C87DC4F7573527AFD6AD97DCB5F9DF9DF6D4BCCFE5CCA90FC9B6ED + DE8600F3B36FE6C298D53153D5864D5B3404DC20EF2EF425049809AC270B2120 + 94080021B67EFD7A193E7CB86CDDBAD5755B848084438059EAD7978E5872BFEC + B81CB065DEC32F6748C63141BD70AE9920B83AFF65EBA31E024E1C7EBDBCF7D9 + B77E34FFB496B90E98FC7DC548490480907BF8E187E58D37DEF0A42D731DF7FE + F1E7C969475958BE3EFD2E0794D15A2E1EDDFED7A4461539B6652369B47FE5D8 + A239E54B169775FABDF873F55AF9E9CFBFE5B5CF16C9FBDFFC28D9DB13BBAD2E + 41F72D7BE9B6D1E5CB96FFDDAB71C56DC326C95D95FFFE4584004200E2470008 + 39B32AE0E8D1A365BB47070642404221E02DAD23927DA1427AD039FBC83632EC + C423A466C572F93E7ECDC6CD32EB9D8F65F2D36FC496D2F543C3DAD5E62C7C78 + 4A9702052CEC9D4308C8D75AFD1E75BB78B27CF4D5F77E34FF94382120E9E303 + 520B012002CC3C00331FC02B8480B84380595EF5C5645EA047DBE632E58C13F4 + C09FF812021BB66C95A9CFBF2DD73DF5BA6C4D70A19D789809A1775D36580801 + A969CDFA8DB110F0F1D73FF8D1FC935A7D8410100A048008D8B061838C193346 + D6ADF3EE53212120EE106096003E2DDE46CDF7F596E167CA909E473993E0B66D + 8BDD179FAB0775D9B42536F6787DFCFD2FD273CA4C5FCE061002221D02CCC651 + A70B2120ED110022E2DD77DFF5FCFF0B1303E39A1858ECF026F556BDFBE5E242 + F93556A268117960FCF9FBBEEDCC1CFC376E7626C565C7F72B6AE6071C3D61BA + 2FEBE71302523B04AC3621E0A2EBE4936F7EF4A3F9C7B5FA0A2120AD11002264 + FAF4E9327FFE7C4FDBE44C40DE6702B6CE7DA0FFB69CDCFBAF7BF079B965D68B + B27ED3DE1757EBD0FC409936EA2C6954A77A1CE3D6DAB4C9B93D2E8E53FCE6E0 + 7FD455771202221A028ED510F0A93F21E031714280AF334FE11F0240846CDCB8 + 51C68D1B179B18E82542C0DE43406EEEF802D91FD6FD527FCD1A9A7F5FB17A9D + 3CFFDEA7F2C1FFBE933FFF5E2DC5F5137F839A55E4D8B62DE4D02675137FD51C + 1DFBDA75A2A922DF871202A21D028E193A49167CFB931FCD3FA03550F2DF4112 + 29880010313FFFFCB34C9E3C593F407ABBEB279703F6BC1CB065DEAC93339C99 + D3FE32970556AF8D0582BCFCBA62951C35FECED86501AF9D79DCE172F7E5E710 + 0252D4AA751B622160E1A2257E347FBFEC63C968A4360240047DFBEDB772E38D + 37CAB66DDE5EBEE34CC0EE6702B67C38EB958C5C393A90F19B89822B56EB5B70 + DEEFC18480E88680E51A128FBE70927CF9C3AF7E346FDEF4070B2120AD100022 + EA934F3E89CD09F06A7D809D3813E09C09C87DFFC1ADD90532974A900BE69889 + 817A80CFDD4E08C84BD44340D70B26CA573FBAD9E4729F080169860010617E85 + 00CE04C89217A68EBEA36BEB6637043E7E332970F94A42403EA21C02FED2EF4F + D70B27CAD7FE8480195AE70A21202D1000228E10E04F08A850A6D4FA79F75E5D + A266958AC18F9F104008C887CF21E01E714280BBBDC8E13B020008013E850073 + F07FE38E2B8410400848457FAE5C130B01DFFCB4D48FE6090169800080184200 + 21801010CD1070D40513E5DB25BE8480A95AC3841090B20800F87F8400420021 + 207A21E08FBF574BD70B27F915026ED71A6A7B8CD83B020076430820041002A2 + 170296FEB5528EBCE05AF9E1B73FFD687EAE38B7C7B26C708A2100600F840042 + 0021C0FB10F0C8B51749F78EA91D02BA9C7FADFCB8D4971060661B36D7F2FE07 + 0B49230060AF080184004240F442C06FFAFFBCCB05D7CA4F4BFFF2A379B30679 + 132D5F1206124700C03E110208018480E885805FFE58113B13F0F3B2E57E346F + 0EFE4DB57C691C892100204F8400420021207A2160C9EFCB6373024C18F0C177 + 5A6DB4BCDF990A092100205F8400420021207A21C05C063097037EF3E1FFBD5A + A8D5456B95ED714619010071210410020801D10B013E5F0E785FEB18ADF5B6C7 + 19550400C48D1040082004442F04985B03BB9C7F8DFCBEDC970FEB6F6A75D3DA + E2B621248E008084100208018480E88580EF7FFD23762660D90A5F42C0E35A7D + 840D8402470040C208018400420021C06353B4C6D81E63D41000901442002180 + 1010BD10B0E8E7DF637B0798E5837D709ED67F6C8F314A0800481A2180104008 + 885E08307B0674183C5ED6ACDFE875D3E68DE414AD676C8F312A080070851040 + 082004442F047CF7CB326975E6E5B269CB56AF9BDEA0758496F7BF54D8030100 + AE110208018480E88580CFBFFB59DA0D1A275BB33DDFE3C7AC1668160AFAC9F6 + 18C38E00004F10020801848068868023CE9D201B367B7E17DFB75AE6979E8582 + 7C44008067080184004240F442C09F2BD748874157C912EF170B7A5DEB5871E6 + 06C0070400788A1040082004442F0464EBCFC809C3A6C89B9F7CE575D3DC1EE8 + 2302003C4708086308D0B784E5AB0801F98872083073014E197DB3BCA2DF030F + E56A9DAEF5A8EDF185110100BE200410020801D10B011B376F95E3874D96B99F + 2DF2B45971E603789A2C4000808F080184004240F442C0AA751B621303BFF969 + A997CDFEA875B0962F2B1045150100BE220410020801D10B0166E320738BE0D2 + BF567AD9EC0B5A278A7359001E2000C0778400420021207A21E0CB1F7E954E43 + AEF67AC5C0E15AB7D81E5B5810001008420021801010BD10F0D6275FC909C3AF + F772B1A06CAD4E5AEFDB1E5B1810001018420021801010BD1030FBD5F765C084 + E9FAABE2D999FB5FB55A6AADB03DB674470040A0080184004240F442C035339E + 926B663EED6593CF6A9D647B5CE98E0080C0110208018480688500F3E9FFCCAB + EE94C75EFFC0CB66076BCDB03DB674460080158400420021205A21C0EC1CD8F9 + BC6BE4D36F7EF4AA49B373A0B914F09DEDB1A52B0200AC210410020801D10A01 + BFEAFFEF36678D95BFE2F81EC5C9FC02995FF46CDB634B470400584508200410 + 02A21502DEFF7C911C3D74929777068CD79A607B5CE9880000EB080184004240 + B442C0ADB35F924B6F9BE55573E678D54EEB23DBE34A370400A40442002120AA + 21E0C90F3E93FEB73D1CA9106026059E76F95479E6ED8FBD6AF25BAD165A9B6D + 8F2D9D100090320801840042407442C0EAF51BE5D00157C84F4BFFF2AA497319 + 60BCED71A5130200520A2180104008884E08F8DFE25FA4C3E0AB62770878C01C + B75A697D667B5CE982008094430820041002A21302A63FF9BA5C7CD3FD5E3537 + 5F9CF900DEBE79841401002989104008F023049C7A541B7960FCF9B19F83C0C5 + 19021E9DBB40064E7B24F673E02513021EBFEE1239AE7DCBE0C79E07331FE0E4 + 5137C98BEF2FF4AA49360C8A130100298B1040082004781B024A142D22EFDC7D + 9534AD5B23F8B1E7E1CF956BA465DF31B27CB527EB039805829A6AFD647B5CA9 + 8E00809446082004443504F87539A055A30364EE8C09929161E152481E5E99F7 + B9741F7183579B063DA3D5C3F698521D0100298F104008886A08F0EB4CC01B77 + 8E95C35B340C7EDCF9387FCA4C99F1CC9B5E35D74DEB65DB634A650400A40542 + 00218010E05D0818DEF738997CE1E9C18F39DF6FC91639B8DF65F2E3D23FBD68 + CEAC0DD04C5826789F0800481B84004240544380D797038E6BD742FE7BE3C8E0 + C71B8777167C235D2F9CE8D5A50033C89B6C8F29551100905608018480A88600 + 2FCF0498D3FFE63240AA3A6FF20C99F9EC5B5E34B54EAB81D632DB634A450400 + A41D4200218010E02E049CD2E53079E4DAA1C18F334E6BF5FB71D0E997CAD2BF + 567AD1DC7D5A036D8F29151100909608018480B08580DCF59B44E2B80DCE8BCB + 01370F3B532E3CF5E8C0C79888E7DFFD547A8EBED98BA6CCB584D6E26C1D8C5D + 100090B608018480B0858020CE0414CECA926F9EB849AA572A1FFCF81274FAD8 + 69F2E49C0FBD68EA35ADD44E3C16100090D60801840042406221E0E2DEC7CA0D + 179F11FCB892F0C7DFABA5C969236397043CD059CB93890561410040DA230410 + 02221B023E582803A7CE8A3B04984580E64CBF528A14CA0A7E4C49BAE1A1E7E5 + 8A3B1FF5A2A98FB40E13E792008400809020041002221702320B4846C572F2DA + A75F49BF2B6F9755EB36E4D95CD7439BC943D75C28654B160F7E2C2E6CCDDE26 + 2DCF1823DFFDE2C944FE13B45EB03DA65441004068100208019109013B0EFE52 + 3033F6AFE654F994079E93C75EFF4056AC5EF7FF0F33CBFDB668504B869F7E5C + 6CE6BF959D103DF0C6475F48B78B277BD1D4175ACDB5BC5D5A314D1100102A84 + 004240E843C0BF0EFEBB323F03DF2EF95D96E9F7A268E1427240F54A52B97C99 + E0FBEC831E66C7C0B90BBC68CA2C8138DBF67852010100A143082004843604E4 + 71F00F3BB33CF0417D46CB966CD72BFB7EA7D548CBDB37883444004028110208 + 01A10B011B378B98C97B113CF8EF34ECE607E58E275EF5A2A953B49EB23D1EDB + 0800082D42002120742120E296AF5E2B07F61C26EB4C1872E7637116078A3402 + 00428D104008200484CBB8FF3C2E931F78D68BA63A6ABD6B7B3C361100107A26 + 04DC7EFBEDE667BAA097ED120208018480E0AD59BF511AF41C262BD7AE77DB94 + B91DF004DBE3B189008048983871E2458B172F36DB827ABA020A218010400808 + 9E478B039905819A6A7D657B3CB6100010091919190DFAF7EF6F7ED9CDED3F84 + 000F1102080141DBB879AB34EC353C76BBA34B91DE2990008048D81100CCED3F + 3D8510E0791708018480A0DDF2C84B327ADA2CB7CD6CD5AAA5E5C93283E98600 + 8048D825001884004280E75D200404CBDC097040F7A1B27AFD46B74D8DD59A68 + 7B3C3610001009FF0A0006218010E079170801C11A3BFD31B9FEC1E7DC36F393 + 565D89E0F2C0040044C25E02804108200478DE05424070FE5CB946EAF5B85836 + 6F75BD3AE0915A736C8F2768040044C23E02804108200478DE05424070865C37 + 43EE7DEE2DB7CD98F780D36D8F2568040044421E01C0200410023CEF02212018 + 669BE0667D46494E4EAE9B66CC64C06A5A2B6C8F2748040044423E01C0200410 + 023CEF022120181EED147889D654DB6309120100911047003008018400CFBB40 + 08F09F39F89B10E0D297E22C0C14197B0B00E6A774DB3EFE2EFF06333264E6CC + 99B12000A48A3803804108200478DE054280BFB66DDF2E757B5C2CBF2F77BD30 + 90D920E863DBE309CABE0EF21BB48A25DBE8D4A953A574E9D2B6C706FCBF0402 + 804108200478DE054280BFAEBAEB09B9EEFE67DC3633456B8CEDB104655F01E0 + 0FAD4AC9363A62C40869DA3452675290E20A142850E7CC33CFFC2981A7100222 + 1A027ED1C71C79D51DF2F3F2959E7761E0899DE43F970D0A7EEC11B0E4F7E572 + 60AF616E27032ED6AA6F7B2C41D9570030BFF90727DB68C78E1DE5ACB3CEB23D + 36E0FF65646454E8DFBF7FA21FEB08018400CFBB70D325FD64E869C7043FF608 + 3866E82479F313D77BFB34D6FADAF65882B0AF00F088569F641B2D58B0A04C9A + 3449F6DB6F3FDBE3038C0D7AF02FA92120998F068480888600BF2E0794285A44 + BE79F266A9548ECBA45E7BECF50FA4DFB83BDC3673A5D6B5B6C712847D050073 + 0DE43A370D3768D040468D1A150B0380651F0F1830A0B58BE71302221A02FC3A + 1370F59053654CFFEEC18F3BE4B66467CBFEDDCE77BB3F80B99F30E933E0E964 + 5F01E030AD796E1B3FE49043E49C73CE9142850AD91E27224C3FF9DFD0BF7FFF + 4B5D364308200478F6D21D9A1F2873A65F19FC9823A0FFF83B65F6ABEFBB6DA6 + 8E387B0484DABE0280F9D8BE5CAB8CDB17A85EBDBA9C7EFAE9D2A85123DB6345 + 74B51F306080EB77042104443604787D39A06AC5B2B2E4B9DB831F6F04FCF7AD + 8FE4B4CB5DAFE7334CEB56DB63F15B5EF7FADFA3E5D974D5AA55ABCA41071D24 + 152A549052A54AD91E37D254666666EC16D39A356BC67B7969B17EFA6F90E4F5 + FFBD2104443404787926A0629952B2F4E5E9C18F3502366CDA22558F1D229BB6 + 6C75D3CCDB5A9D6C8FC56F7905800E5AEFDAEE20B037458A149156AD5AC94927 + 9D24E5CB97CFEBA183F4D3FF4C8F5F9E1010C610F09786809C604240F3FAB5E4 + A30722B9057D207A8EBE599E7FF753374D98F4504E9C3571422BBFD5FECC8A48 + 87D8EE24B02F595959B15B4EDBB6DDEB41F3CB2D5BB6B43CF7DC735DEF15BA17 + 8480308680802E075CD2A79B5C7F51DFE0C718110FBDF49E9C7DCD7FDC3663EE + D57CD5F658FC945F003859EB29DB9D04F262969F3EEFBCF3A475EBDD26FA67EB + 7F6FDFBF7FFF8F7C7C6942404443809B3301050A64C847F74F9266F56A043FBE + 8858B976BD54EF767E6C896017AED71A6D7B2C7ECA2F0098BF7F4FAB9DED8E02 + 79319704A64C99F2FF4B50EBC17FA81EFC8398654508200424D47CFFE33BCA3D + 579C13FCB822E6E8A193E42D778B02996B08A13E031ECF863FCD767C23B8A11F + 29AD6BD7AEB13B4EF4E03F590FFE9705F8D28480A8868095ABE5A8F1D365C9B2 + E57135DBF2C0DAF2E6F47152AC08B746FBEDFA079F93B1D31F73D384397D60EE + 845B6F7B2C7E8977C7BFB15AD7D8EE2C90177377C92DB7DC72D9D9679F3DD9C2 + CB1302A21602320B4846C572B27CFD06E93B769ABCFD69DEABC7F6E8D45A668C + 3D574A162B12FC5822E8E3AF7F9076678F73DB8CB913E06DDB63F14BBC01C06C + 5FF58AD651B63B0CE4A3B6D6124BAF4D08884A08D871F09782993BBE4DB9F2FC + 7B9FCA8C67DE8C0581CD5B9D79A766D9DF2EAD9BC879A77495CE87340EBEFF11 + 667E26AB1E334456AD733591FF7271B92A6E2A8B370018E654C83BE25C120052 + 9559C572BEC5D72704843D04FCEBE0BFE7B72B57FE5CB94632F571E67E7FD8D3 + 63D44DF2E2DC056E9A784E2BB46B362712008CAAE29C0EA967BBE3C03E34D4FA + D6721F0801610D01FAC7BC0EFE482D1ECC0330333CCD0F5C8E9B465255A201C0 + 305BFCBD28219F1D89B4B449ABFC8EAFB61102C21602B2B799DB4B38F8A79177 + 177E23479EEF7A63BFE65A9FDB1E8B1F92090046092DB3CA022B5920953CAB75 + 92ED4EEC821010B61080B4B271F356A970E420B7EB0184765F806403C04E03B5 + 6E120F360D025C326767DB88DDEBFF7B43082004C0A23603AF944FBFF9D14D13 + A19D07E0360018E692C014AD7E5A9C1B832D26A10FB3DD897D2004100260C965 + B7CF969B66BDE0A609FD418F1DE75CED2E948ABC08003B99898166D9C43E5AC5 + 6C0F0C91F2903867A3B6D9EE481E0801840058F0D2FB0BE5A49137BA6DC69C01 + 78CEF658BCE66500D8A9A4386F76E65A6C47E1F200FCB34CEB4A2DAF77FBF30B + 2180108080ADDBB8592A753DC7ED3C80C7B54EB33D16AFF9110076652E0934D1 + 3A50AB81560571261096B03D70A4ADCD5A4BC5D9A3E2CD1DFF9E4E0801840004 + CCAC0868560674C1BCCF5416E7724068F81D0000EC891040084080AE99F9B45C + 33C3F5C6B603B41EB03D162F1100003B0801840004E487DFFE9486BD86BB6DE6 + 0309D9CEB80400C01E42002100013974C015B270D112B7CD985B8D3FB43D16AF + 100000BB0801840004E0E6592FCA98DB1F71DB8C5957B8B7EDB178850000D847 + 082004C067CB56AC92DADD874A4E4EAE9B66CCAD04E696F79F6C8FC70B040020 + 3510020801F059B78B27CB1B1F7DE1B619B3FAED48DB63F1020100481D840042 + 007C64B606365B04BB64361B33670196DA1E8F5B040020B510020801F049AEFE + 2C36E93D4A16FFB2CC6D53D3B42EB23D1EB7080040EA21041002E093DB1E7B45 + 46DEFA90DB66CCBE006681BBB49E0B40000052532F2D3365B9A0978D6615CC94 + 87AFBE507A746A1DFC8812080103A73D228FCE5DE07917EAD5A822EFDD335ECA + 956231D2A8324B03D73EF14259BB6193DBA6CC12E4836C8FC70D020090BA0801 + 3E8480A30E6D2A2FDE3A26F8B123658CB8F52199F6D82B6E9B319B8F1DA4F5B5 + EDF1248B0000A43642800F21E0BF378E94E3DAB5087EEC4809CB56AC9686BD86 + C9C6CDAE77F835FB9174B13D9E64110080D4C79C008FE7041CD7BEA5FCF78611 + C18F1B29C3CC03B8CDFD5900C3FC7E3E6D7B3CC9200000E98133011E9E09285E + B4B0AC9C33533232780B8CAA3FFE5E2D079EE2C959805FB51A6A6DB03DA644F1 + D30FA40F4280872160D92B7749F9D24C068CB2D1D366C92D8FBCE4455313B4C6 + DB1E4FA20800407AE17280479703FE7AFD1E2953A258F0E345CAF86BD55A39B0 + E73059BF69B3DBA64C03CDB516D91E5322080040FA09DF9900C91559B15A72F3 + 391DEBD5998052C58BCA720D005C02C0A4FB9E91F1773FE14553F3B4DA6BE5D8 + 1E53BCF8E907D21367025C9C0938B9736B7974E2C5C18F112967F3D66C69DA7B + 94FCBC6CB917CD0DD5BADDF698E2450000D2172120C910F0EAB4CBA5D3218D83 + 1F1F52D2E3AFCF9333C67972DC3613019B69FD687B4CF1200000E92D7C97037C + 9E1868C6F4D8243EFDE31F668F804E43AE960FFEF79D17CDBDAA75ACC4AE6BA5 + 36020090FEA21B02F41DEC9C194FCBC3AFCC8DABD99607D696D7EF182B258B15 + 097E4C48699F7CF3A3B41F344E72723C396E5FA87587ED31E58700008443F442 + 406601C9A8584E72F5ABB995EBEA194FEEF39EEE020532A45FB7C365EA880152 + AC48A1E0C782B470FE949932E39937BD68CADC15D04AEB4BDB63CA0B0100088F + E884801D077FD1BEED649677BDF7B9B7E4B50FFF274B96FD25DBB6E548958A65 + E488968DE4CCE33A4AB37A3582EF3FD2CA9AF51BA5599F4BF567699517CD2DD4 + 3A4C9C9D0353120100F08E39F056D5AAA9554BAB8A38BF63BF6B9973D4416C1D + 1AFE89817B39F8035E79E28D0FA5EF95D3BC6A6EB2D665B6C7B42F0400207145 + C5D905EC102DB3A34C3D710EFAE6E0BFAF4FDFE6C2E21CADD15ADEEF6EB3BBF0 + 8680EC6C0EFEF05DF71137C8CB1F7CE64553664D8023B5DEB23DA6BD210000F9 + 6B22CE021FE6807FF08E7F4FF6347BB6D6455AFFF1B9CFE10B0126436DD7F7D3 + 4C0EFEF0975913A079DFD1B261D316F78D89FC21CE07853F6C8FEBDF0800C09E + CA6875D33A469CF45EC5E3F6CDD9807E5AB37C1E47084300108C698FBD22236E + 7DC8ABE6CCCCC2AE5ADB6D8F6B570400C0515AEB14710E9A667F6FBFA78AAFD1 + 6A24CEFC003F1102802498DB018F1E3A51DE59F08D574D5EAD7595ED71ED8A00 + 80282B20CEC17E80560F71AEED076992D61501BC0E21004882B914D0F28C31B2 + 6EA3EBCD820C331FC09C557CDDF6B8762200208ACC1EB0676A99E5E0EA5BECC7 + 0F5A75037A2D42009004736BE990EB6678D5DC0A2D733F6D107704E58B008028 + 29A7354C9C55BACAD8EE8C3873014C3FD606F47A840020091EDE156098C581CC + 2FCB3ADBE32200200ACC817FB838B3EF4BDAEECCBF5413FFE701EC8A100024C8 + 2C327570BF31B262B567C7EC67B54E16CB5B0713001066E656BD215A13C40901 + A926B757870E959E78EF3D4FF6214D00210048D08BEF2F949347DD14DB38C823 + D76A5D69734C04008455672DB39C5723DB1DD9977A35AAC8578FDDE8FC4B86AC + 965C31371DAFD53FAFD0F798BF3324E36F7DB3599E51407ED37FFF3523577ECB + 2A94F36BC621FD9679F0F284002041E6B640737BA0474C92E8ADF5B8ADF11000 + 1036E676BEEBB5064B8AFF7C5F31B0875C35F894649EBA5EDF3ABE958CDC6F35 + 147C9D23F26D6E4EEED7858B6CFC31E39073B3136887100024604B76B61C3E78 + BC2C5CB4C4AB26376975D4FAD8C67852FA0D12489059BCE71E7196E44D69654A + 14932FF4D37FA572A5BD6CD61CFC176B7DA1353F43723F2AB839FBD38C4E67E5 + 750F13210048C0E25F96C9A103C6CAFA4D9EDC1A68FC2ACECE817F063D160200 + C2C02CDA63EEA93713FD52FE673A232323B6BB5EAF230F0BE2E5B225573ED7EF + CA875A1FE56464CE2F7268EFEFFEF51842009080875F7E4F065EEDE96ADE1F88 + 73D9D293B587E395F26F96403ECC263CE61A9A85BD6A135728ABA04C1B75969C + 75C21136BBF1976690777245DED8BE5D5E2DDAAEEFCF4208001272DEE41932F3 + 594FF7F8B94F6B6090632000209DB5D37A5A6B3FDB1DC94F8102197254EB6672 + DD857DA4C901FBDBEECEEE326491E4E6CE1972DDCC0DF73EF7D625420800F2B5 + 796BB61C71EE0459F0ADA76BFA98A582AF0E6A0C0400A4AB01E2ECA857D87647 + 7655A4509654AF545E6A6899AF352B57904675AACBA18DEBC6FE3DD53DFDE647 + DBCE18372D73DBF61C4FDF1B08010823B354B0990FB072ED7A2F9B3513983D5B + 7A302F0400A4A3CBC4B9E66F55CD2A15A545835AD2BC7EADD8D783EAD594AA15 + CBDAEE966BFF7DEB233963DCED92BDCDDB8DCB08010823B342608F5137C6360F + F2C8367116097ADEEFBE1300904ECCCFEB755AA36DBCB899B1DFF5B06672F461 + 0749E7564DA44299545B54D03B4FBD395FFA8DBB43B66DF736046415CC94176E + 192D9D0E696C7B888067AE99F1945C33F3692F9BDC28CE46651FFAD96F0200D2 + 85F959BD4D9C75FC036316EBE97B4C7B39B66D73FDA45F3336833F2AFC0A01E5 + 4B97902F1EBD31D4010AD1623EFDF7BAEC1679FEDD4FBD6CD66C1CD45E6B915F + FD8ECEBB19D2DD6409E8937FE1AC2C39BE434B19745267E9AC9F54A374D0FF37 + BF42C0B0D3BBC994A17D6D0F0FF08C5917A0C3A0ABE4AB1F7FF3B259D3589B1D + 5F3D17DD7736A4932BC45937DB57E69AFEC5BD8F95BEC7B697B2258BDB1E73CA + F0634EC07E654BC92F2FDC19BB3B02088B1F97FE296D078EF37A52A0D986D0AC + 16E8F9AEA1FCF621D59D2D3ECF88AD5D6D3FB9E2AC1ED2E7E876B16BD4D8931F + 6702BE78F406695033E5176D041232E7E32FE58461D77B7DD66C8E382B9D6EF5 + B2510200529949BDAF89B3D29FE7CCA7FCCBCE3A49CE3BE5A8D8697FE4CDEB10 + F0DAED57C81107A7EC5E4D40D26E7FFC55197ECB835E37FB94389B076DF3AA41 + 020052552DAD8FB42AFAD178CFCE87CAD4910362A7A2113F2F2F07CC9D31415A + 37AE6B7B48802F4C003041C0630F6BF5D7CAF1A2310200525111ADF95ACDBC6E + B84A853272F715E7C46EE54372BC381360AEFDFFFAE29D52B10C010CE1B43D27 + 474EBDEC56AFEF0C30CC8667E78AB39DB02B0400A4A2DBB52EF0BAD1A30E6D2A + 33AF1C2295CB97B13DBEB4E73604B46A7480BC3F33B0154F012B366DD92A5D2F + 9C28F3BFFCDEEBA6A7695DE4B6110200528D99E8F28278F8B3696EE31B79C6F1 + 72CD90D39875EE21379703664FBC2876190608BB15ABD74987C157C90FBF79BE + DBEF44ADB16E1AE0DD10A9C44C09FF9F96678BE6972C56441E9C70811CD7BEA5 + EDB18552326702CCA24ACFDC3832D2EB2B205A16FDFCBB1C3E78BCAC5AB7C1EB + A6CD2DD2492F8BCE6F205289D98EB6B7578D9959FECFDE3C4A0E6B52CFF6B842 + ED99B73F960113EE948D9BF3BF43C94CFA7BE1D6D152A64431DBDD060235F7B3 + 4572EC45D7C996EC6CAF9BBE54EB86649E480040AA3842CBB3CDB5AB54282BAF + DC769934AC5DCDF6B82261E1A22572FE9499F2E9373FEEF5EF0B651594734F3E + 52269EDF3BB6632210458FBEF681F41F7FA7E4E67AB67190611A3373A6A627FA + 4402005241412D3355D69359FF668DF939775EC9C13F60E64DEDCD4FBE9217E7 + 2E90EF7FFD43D6ACDF2495CA9796B6CDEAC7AEF7EF9F06DB21037EBBEEFE67E4 + AABB9EF0BA5913022E16677260DC080048056769DDEB4543A54B1493D7EFB822 + B6452F00A4A221D7CD907B9FF3EC84E74E09870002006C333F835F68B9DE1FD6 + EC37FFD4F5C3A55BBB16B6C70400FB64D6083093679F9CE3F96EBF26040CD7BA + 359E07130060DB895ACF7AD1D02DC3CF940B7A1D6D7B3C0090AFADD9DBE494D1 + 37CB2BF33EF7A3F9CBB5AECBEF410400D8F692D6B16E1B39A5CB61F2C8B5436D + 8F0500E2B661D316E976F16499F7C5777E343F4AEBC6BC1E4000804D66493EB3 + 3A86ABCD7ECCF2BE0B1E9E22E54B97B03D1E0048C8EAF51BE5C8F3AF91FF2DFE + C58FE6476ADDB4AFBF2400C0A67E5AAEB6CC328BC9984565CCE23200908EFE5C + B9463A9F778D2CFE6599D74D9B3901BDC4D949700F0400D834536BA09B0638F5 + 0F200C7EFDF36FE978EE04F94DBF7A6CB996D97673EDBFFF8200009BCCBDFF49 + AFD15B382B4BFE37FB7AA95D6D3FDBE30000D7BEFB6599741E72B5FCB56AADFB + C676B7D74B010400D8627EF63669154EB601B3BBDFAC6B2F62595900A1F1F9E2 + 9FE5A8F3AF8DCD0DF0D07B5A87FFFB3F1200604B512DD73FE1053333A5519D6A + 52BF4655ADCAD2A06655A9BB7F65A95AA1AC942F5392656701A41DB37DF07197 + 4C96B51B3679D5A4B9AE50E1DFFF9100005BCA6AADF4FB458A172D2C15CA9492 + FDCA969252C58B4AE992C5A444D12252BC48612951AC889429593CF6987FFFFB + CEC79429553CF6E7AC8299B6BF5F0022C48480E3874D9135DE9C09303B10ED71 + B7150100B6988FE626DEA6C591D58402B3CCB0D961B0AC86021314CA9470FE6C + AA5AC57252A95C69A9B69FF3D514DBDD0270C3C310F0BBD61E9BA3F00E059B7E + D5AA6EBB137E309726F62B572A160CAA572A2F0D6A5491FA35ABC42E51D4D33F + 336F01403C3C0A01E636C053FEFD1F0900B0E969AD1EB63B6183394360C28009 + 054D0FA8218734AA2307D5AB19DB36170076E5410838556B8F2D080900B0E96C + AD19B63B912ACCC1DF84800E2D0E948E2D1BC5BE9AF90700E022047CA675B056 + CEBFFF8200009B8A6BFDA455D176475291B98C7058D3BA725CFB967252C75672 + 40F54AB6BB04C0A22442C01AADD65A7BDD6C800000DBCC8615D7DBEE443A6854 + A7BA9C76541B39B3DBE1B1C98600A2C7EC1970CA989B65C9EFCBF37BA8D95CC0 + ECB6BACFED060900B0CD5CF47E5BAB9DED8EA48BCC0205628B200D3AA9B31CDF + FE602950805F63204ACC1980DB1E7D59EE7AFA8DBDAD1A683658339756CD07AB + 3C9714E49D03A9A086382B55D5B0DD91746326128E38E37839FDE8764C200422 + 26272757BEF8E197D8FE01E6CF190532EE3B79D44D83642FD7FBF78600805471 + 80D65B5AFBDBEE483A32B71A4E3CEF34E9DDB52DEB0F00D1F5BF426DFA1E14EF + 8379A7402A31B3DC1ED1EA6CBB23E9AA75E3BA72F3B07EB1AF002227276B7356 + E98C4EA7AE8FE7C10400A41AB332E030ADB15AA56D77261D993901E7F5EC2AD7 + 9E775A6C054300D1919321F58B1CD677713C8F25002055993D7EAFD41AA055C2 + 7667D251ADAA1565FA9841D2A55513DB5D0110908C8C8C0E59879D3E37AEC7DA + EE2C908F325A6769F5D36A61BB33E9C6CC071878E21132F9C2D3637B190008B7 + DC0C39A9F0617D9F8DE7B10400A4137397C0F15A1DC559DCA296ED0EA58BAA15 + CBCA9DA3CF966EEDC850409871060051612E133415E70E823A5A35C5D9F1CAFC + F7AA5A256D7730D59C7E4C7BB9E9927E52BE3457558030CA2928071469D5F7C7 + 781E4B004098991BE34B897319A1F48E2AB5CBD7123BAAF08EFF566CC79FCBEE + F85A7CC773CBEC787C286EB4371B11DD367280F4E8D4DA765700786B7BD6E6AD + 25323A9DB5399E07130080F89940504A760F1115C4B97DD19439EB60CE3EEC3C + 0B61AA80ED4EEF4BAF230F93A923064885329C280142E2D3426DFA1E12EF8309 + 00807FCC2D8D260CD4DDA51A6B3517272C5867CE06DC7EE940E9DE31EEF70C00 + 292A57E4DAC26DFA5E19EFE30900801DE6EC80999167F64038429C498DD66EDA + 3FEDA8B672EB88FECC0D00D2576EAE64362EDCA6F737F13E810000A486225AED + B54ED63A49AB4AD01DA85CBE8CDC71E94039E1F0836D7F2F0024283737F7C5C2 + 6DCF383E91E7100080D463E60DB4D53A5BABB738E12030E64E01B39C70B9529C + 0D00D2448EFED3AA509B7E0B1279120100486D6692A1D9DDEB62ADCA41BD6895 + 0A656213044F3AA295EDF103C8DFED85DAF41D9AE8930800407A3077205CA875 + 8504B8BEC171ED5AC8D49103A446E50AB6C70F606F32E4B3AC4D5BDBC47BEBDF + EE4F05904ECCDD03376AF509EA054B142D22E3CFED2517F4EA2A990552F6AE46 + 208A7ED996BBAD6DB1B6FD9726F3640200909EBA69DDA5553DA8176C56AF466C + 73A1568D0EB03D7620F2322463E9F68CDC4EF1EEFCB7F73600A42BB318D1F55A + 8325A0DF65B3D5F0C0133BC994A17DA564B140E72602D8215772FF1029D83991 + 5BFEF6860000A4BFC3B56668D50BEA05AB54282BB70C3B534EEECC72C24090BC + 3AF81B0400201CCC3D7B93B42E9000971F369304A75CD457EAD7087CD9022072 + BC3CF81B0400205CCCFA0133B50E0CEA05B30A664AFFE33BCA84737B49C532A5 + 6C8F1F0825AF0FFE060100089FA25AE3B54688B31F4120CC32C2570EEA29834F + EA120B0500BCE1C7C1DF200000E165361DBA6FC7D7C0983503C6F4EF2E679D78 + 04B70D022E7931DB7FDF6D0308B32CADE15AD7ECF873600EAC554DAE1ADC534E + EED45A323278AB0112E5D727FF9DF8AD04A2C1ACE97BAF5693A05FB845835A32 + 76E0C9725CFB96B1DB0801E4CFEF83BFC16F23101D3BCF065CAD5528E8173FA0 + 7A2539FF94AE32B84717295228D09311405AF1F3B4FFEEAF03206A9A893337A0 + A58D17AF54AEB49CA3216068EF63A54C8962B6BF17404A09E293FF4E0400209A + CC1980B15A6324E0B9013B95D6837FDF63DAC7C240A33A81AD680CA4AC200FFE + 06010088363327E01EADC36C76A2E581B56550F7CED2F7D8F652B470E0572700 + EB823AEDBFFB6B02883A73AF9E594170A204B8D5F0DEEC57B694F4EB76B89C7E + 4C3B695AB786EDEF0B1088A03FF9EF440000B0D3FE5A77689D60BB2346E33AD5 + E5B4AE6DA58F56CD2A156D7707F085AD83BF410000F06FDDB56ED5AA65BB2386 + 5943E0B026F5A4B70681EE1D0F91AA15CBDAEE12E0091BA7FD777F7D00D89359 + 4E78F48E4AA97D7F1BD6AE26C7B76F29DDDAB590364DEBB3B600D292CD4FFE3B + F19B03202FF5B56ED33ADA7647F6A672F932B120D0AD5D73E9D0A2A1942D59DC + 7697807CD9FEE4FF4F3F00207F476ADDACD5D47647F252BBDA7ED2A555935875 + 6CD9482A94B13AA711D8432A7CF2DF890000205E05B5066B4DD04AF9597966EE + 40A3DAD5E4F0160DE5B0A6F562B71AD6DBBF0A970C604D2A1DFC0D7E130024AA + B4D6655A17893357206D94285A449A37A8292D1AD496965A669F8206B5AAB26B + 217C972AA7FD77EF130024A78A3841E01CADC2B63B93ACE2450B4BA3DAD5A57E + CD2A52BF46156950A3AAD4AB5159AB0A7B16C013A9F6C97F27020000B7CCFA01 + 57689D25163619F28BB95450A37205A9BF7F95581830F30BAA572C2755F72B2B + 352A55904AE54B73E600F94AC54FFEFFF40D00BC514BEB72AD33258DCF08C4AB + 6066662C04983060D626A8BE5F39D95F0343AD2A15620B179962B3A3684BD54F + FE3B11000078ADB2D650ADF3B422BD6A8F0900260898CB0B6612626CEE817E25 + 18845FAA1FFC0D020000BF94D03A5B6B98564DDB9D4925E672C2C107D6910ECD + 0F942EAD9BC4E61E203C52F9B4FFEEFD04007F99DB077B689DABD55978DFD943 + B5FDCAFDFFFA055D5A378D6D8A84F4940E9FFC77E217114090EA6A0D1267C2E0 + 7EB63B938ACCE443B3F741CFCE87CA295D0E952A15227D1525ADA4CB27FF7FFA + 0B00C13393044F166761A18EE26C498C7F3161A05DB306D25383C0A947B66165 + C314964E9FFC77220000B0AD9AD6295ABDB4DA0AEF4B7B5528ABA09CD0E16039 + E3D8F6724CDBE6DC829842D2ED93FF3FFD0680D4514FABB7561FAD86B63B93AA + 6A55AD28038E3F42069E78446C4324D893AE077FA7EF00909ACCC643C7691DAF + 759856A6ED0EA59AC25959D2E7E8B672499F6ED2A84E75DBDD899C743CEDBF2B + 02008074504EAB8B38BB1276D7AA64BB43A9A66DB3FA32AADF09B1ED91CD4648 + F0573A7FF2FF670C00905ECC998036E2DC5278B83867078ADBEE54AA38A4611D + B972504F39B66D73DB5D09AD301CFC9D7100407A33EB0C1CA4D55EAB9D38670A + CAD9EE946D8736A92B63FA7797E3DAB7B4DD955049F7D3FEBB220000081B7386 + C0CC1F68AD658E7E2DB49A6915B1DD311BCCA5816BCFEB2DED9B37B0DD95B417 + A683BF4100001005E62C41237102C1CE32670D4AD8EE58504E3AA2955C77411F + 39A03AD327921196D3FEBB8F0900A2CB2CB3D7589C70506747997F371F974377 + D74156C14CE97F7C4799706E2FA95886E586E315B64FFE3B110000604F85C459 + B6D804811A5AFB8BB36091F96AEEB7ABAA9565BB93C92A5FBA845C3DE45439FB + C4CEB1D506B16F61FCE4FFCFD800008932CBF09973E9BB060313146A6BD5DAF1 + 35E517F16FDDB8AEDC7EE959D2BC7E2DDB5D494961FDE4BF13010000FC515A9C + CB0987681DBCE36BCA5D5A304B0A9FDFABAB5C35F8142955BCA8EDEEA48C307F + F2FF678C0080A0984987E656C5AE5A478973B7424A305B12DF39FA6CD60F90F0 + 7FF2DF89000000F65411270C989D118F16679744ABFA75EB20375ED24FCA968C + E6DA4A51F8E4FFCF580100A9C05C3230CB1C9F2ACED98142B63A52A54259B973 + F4C0C82D2214954FFE3B11000020F5982DFE4C1018AAD5C45627FA1EDB5EA68D + 3A4B4A140DFF1A4A51FAE4FFCF980100A9CABC471FA1758E389709023F2B50AF + 46157960FCF9B13D06C22A6A9FFC77220000407A30EB0F5C224E182819E40B9B + 0584C60D3E45469D7142E8D60D88EAC1DF08D7FF4900083F7379E03CAD8B25E0 + 6D91BBB46A220F4CB840F62B1B8E5504A378DA7FF7F10300D25131ADC15A9749 + 8041C01CFC4D083061209D45F993FF4E040000486FE6E3F870AD613BFEECBB82 + 999972D539A7C8A5FD4E908C8CF43B8C44FD93FF3FDF0700401894D7BA5A9C39 + 0205837841B3C3E07DE3CE93E245AD2F5F10373EF9FF83000000E162961BBE59 + AB5B102FD6B46E0D79FAFAE152B34A45DBE3CE1707FFDD110000209CCCA242B7 + 8AB33991AFCCBC8047275D22ED9B37B03DE67DE2B4FF9E080000105E66779FD1 + E24C14F4750D01332FE0C64BCE90F34FE96A7BCC7BE093FFDE11000020FC9A69 + DDA57598DF2F34E8A4CE3275C480D8DA01A98083FFBE110000201ACC11D9DC2D + 60260AFABAB6AFB945F091891759DF5088837FDE080000102D8DB4EED76AE5E7 + 8B34AC5D4D5EBC65B454AF54DECA2039F8E78F000000D1636E13BC42EB4A71CE + 0CF8A246E50AF2D2D43152BF46954007C7C13F3E04000088AEC3B51ED1AAE6D7 + 0B942B5542FE7BE30869D3B47E200362B67FFC080000106D15B41ED43AD6AF17 + 300B05CD9E78B11CD3E6205F07C227FFC410000000E6587091D60D5A597EBC80 + B94DF0CE3167CB80E33BFA32000EFE892300000076F2F59280D93760C6D873A5 + 5FB70E9EB6CBC13F39040000C0AECC9ABE0F691DED47E385B20ACA5BFF1927AD + 1A1DE0497B1CFC9347000000FC9BB93360B2D6483F1A3FB4495D79EF9E09AEDB + 894DF8CBDD7E4491B6FDBE0FF8FB130A040000C0BEF4D1BA577C5838E8A30726 + 4AF3FAB5927E3E9FFCDD23000000F2622ED83F2DCEDD029E99787E6F19D5EF84 + A49ECBC1DF1B040000407EEA683DA7D5D8AB06CD9E01778E3E3BE1E7E941EBB7 + EDB9399D38EDEF1E010000108F125AB3B44EF4A2B1C12775913B460F4CE8391C + FCBD45000000C4CB4C0EFC8FD620B70D5D35F814B962608F449EF2734E6ECE91 + 1CFCBD4300000024C21C37266A5DE6A691B7EFBA4ADA368B7B79E005D9DB0B9C + 50BC7D9FDF6D0F3E4C08000080645CA83555AB40A24F6C54A7BA2C7868B21428 + 90EF2168BB64644CCB5A59664C46B76E5B6C0F386C08000080649D21CE6D8271 + 2F1F6C0EFA2FDC325A8E6CDD34AF87E566E4CA73B9993957153AB4DFE7B60719 + 56040000801BDDB41ED72A1ECF83AF19725AF6E8FE27EE2D306CD57A570F4BCF + E9C7FEE78BB6E9B3C4F6C0C28E00000070CB7C9C3721E0C03C1EB35AEBE2DCAF + 1E7F74D39A4D150B6616A890B13DA3426E66E69AACCC6D4BE5E033FEC8C8D0CF + FD080C010000E085825A7DB57A6BB5D12AADB559EB2B71D610B8536B85ED4EE2 + 1F040000801F0A89735A1F298A00000040041100000088200200000011440000 + 0020820800000044100100008008220000001041040000002288000000400411 + 0000008820020000001144000000208208000000441001000080082200000010 + 4104000000228800000040041100000088200200000011440000002082080000 + 0044100100008008220000001041040000002288000000400411000000882002 + 0000001144000000208208000000441001000080082200000010410400000022 + 8800000040041100000088A0FF038B4680771631B7DA0000000049454E44AE42 + 6082} + Proportional = True + ShowHint = True + Stretch = True + ExplicitLeft = 10 + end + end + object RadioGroup1: TRadioGroup + Left = 272 + Top = 40 + Width = 146 + Height = 105 + Anchors = [akTop, akRight] + Caption = 'Function' + DefaultHeaderFont = False + HeaderFont.Charset = DEFAULT_CHARSET + HeaderFont.Color = clWindowText + HeaderFont.Height = -12 + HeaderFont.Name = 'Segoe UI' + HeaderFont.Style = [] + ItemIndex = 0 + Items.Strings = ( + 'GetShellIcon' + 'GetThumbnail' + 'GetFileIcon' + 'GetSysImageListIcon') + TabOrder = 3 + ExplicitLeft = 268 + end + object Button1: TButton + Left = 435 + Top = 48 + Width = 124 + Height = 89 + Anchors = [akTop, akRight] + Caption = 'Extract' + TabOrder = 1 + OnClick = Button1Click + ExplicitLeft = 431 + end + object RadioGroup2: TRadioGroup + Left = 272 + Top = 152 + Width = 147 + Height = 105 + Anchors = [akTop, akRight] + Caption = 'Extract size' + ItemIndex = 3 + Items.Strings = ( + 'Small' + 'Large' + 'Extra' + 'Jumbo') + TabOrder = 4 + ExplicitLeft = 268 + end + object CheckBox1: TCheckBox + Left = 353 + Top = 151 + Width = 56 + Height = 17 + Anchors = [akTop, akRight] + Caption = 'Actual' + TabOrder = 5 + OnClick = CheckBox1Click + ExplicitLeft = 349 + end + object Edit1: TEdit + Left = 364 + Top = 99 + Width = 33 + Height = 21 + Anchors = [akTop, akRight] + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Segoe UI' + Font.Style = [] + ParentFont = False + TabOrder = 6 + Text = '0' + ExplicitLeft = 360 + end + object UpDown1: TUpDown + Left = 397 + Top = 99 + Width = 16 + Height = 21 + Anchors = [akTop, akRight] + Associate = Edit1 + TabOrder = 7 + ExplicitLeft = 393 + end +end diff --git a/ExampleUnit.pas b/ExampleUnit.pas new file mode 100644 index 0000000..c4cdb33 --- /dev/null +++ b/ExampleUnit.pas @@ -0,0 +1,212 @@ +unit ExampleUnit; + +interface + +uses + Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, + Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, + Vcl.Mask, Vcl.ComCtrls, Vcl.Imaging.pngimage, + JvExMask, JvToolEdit, + Vcl.DragFiles, // https://github.com/ps147258/others_vcl/blob/master/Vcl.DragFiles.pas + Winapi.FileThumbnail; + +type + TExampleForm1 = class(TForm) + JvFilenameEdit1: TJvFilenameEdit; + RadioGroup1: TRadioGroup; + RadioGroup2: TRadioGroup; + CheckBox1: TCheckBox; + Edit1: TEdit; + UpDown1: TUpDown; + Button1: TButton; + Panel1: TPanel; + Image1: TImage; + Image2: TImage; + procedure FormCreate(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure Button1Click(Sender: TObject); + procedure CheckBox1Click(Sender: TObject); + private + { Private declarations } + DropFiles: TDropFiles; + procedure OnDropEvent(Sender: TObject; WinControl: TWinControl); + procedure UpdateExtractSize; + function GetPixels(SizeType: TIconSizeType): TSize; inline; + function GetSize(SizeType: TIconSizeType): Word; inline; + function ExecShellIcon(SizeType: TIconSizeType): Boolean; + function ExecThumbnail(SizeType: TIconSizeType): Boolean; + function ExecFileIcon(Index: Integer; SizeType: TIconSizeType): Boolean; + function ExecSysImageListIcon(SizeType: TIconSizeType): Boolean; + public + { Public declarations } + end; + +var + ExampleForm1: TExampleForm1; + +implementation + +//uses +// Debug; + +{$R *.dfm} + +procedure TExampleForm1.FormCreate(Sender: TObject); +begin + UpdateExtractSize; +end; + +procedure TExampleForm1.FormShow(Sender: TObject); +begin + DropFiles := TDropFiles.Create(Panel1, OnDropEvent); +end; + +procedure TExampleForm1.OnDropEvent(Sender: TObject; WinControl: TWinControl); +begin + JvFilenameEdit1.FileName := TDropFiles(Sender).First; + Button1.Click; +end; + +procedure TExampleForm1.UpdateExtractSize; +var + Mode: TIconSizeType; + Modes: TIconSizeTypes; + function TypicallyStr(M: TIconSizeType): string; + begin + Result := Format('%s[%d]', [M.Str, M.TypicallySize]); + end; + function ActualStr(M: TIconSizeType): string; + var + Size: TSize; + begin + Size := M.ActualPixels; + Result := Format('%s[%dx%d]', [M.Str, Size.cx, Size.cy]); + end; + procedure SetExtractStr(M: TIconSizeType; const S: string); + var + Strings: TStrings; + begin + Strings := RadioGroup2.Items; + if Integer(M) < Strings.Count then + Strings[Integer(M)] := S + else + Strings.Add(S); + end; +begin + if CheckBox1.Checked then + begin + Modes := CatchImageListAll; + for Mode := _IconBase to _IconBest do + if Mode in Modes then + SetExtractStr(Mode, ActualStr(Mode)) + else + SetExtractStr(Mode, TypicallyStr(Mode)); + Exit; + end; + + for Mode := _IconBase to _IconBest do + SetExtractStr(Mode, TypicallyStr(Mode)); +end; + +procedure TExampleForm1.CheckBox1Click(Sender: TObject); +begin + UpdateExtractSize; +end; + +procedure TExampleForm1.Button1Click(Sender: TObject); +var + Succeed: Boolean; + SizeType: TIconSizeType; +begin + SizeType := TIconSizeType(RadioGroup2.ItemIndex); + case RadioGroup1.ItemIndex of + 0: Succeed := ExecShellIcon(SizeType); + 1: Succeed := ExecThumbnail(SizeType); + 2: Succeed := ExecFileIcon(UpDown1.Position, SizeType); + 3: Succeed := ExecSysImageListIcon(SizeType); + else Succeed := False; + end; + if not Succeed then + Image1.Picture.Assign(nil) +end; + +function TExampleForm1.GetPixels(SizeType: TIconSizeType): TSize; +begin + if CheckBox1.Checked then + Result := SizeType.ActualPixels + else + Result := SizeType.TypicallyPixels; +end; + +function TExampleForm1.GetSize(SizeType: TIconSizeType): Word; + function MaxPixels(S: TSize): Word; inline; + begin + if S.cy > S.cx then + Result := S.cy + else + Result := S.cx; + end; +begin + if CheckBox1.Checked then + Result := MaxPixels(SizeType.ActualPixels) + else + Result := SizeType.TypicallySize; +end; + +function TExampleForm1.ExecShellIcon(SizeType: TIconSizeType): Boolean; +var + Icon: TIcon; +begin + Result := GetShellIcon(Icon, JvFilenameEdit1.FileName, GetPixels(SizeType)); + if not Result then Exit; + try + Caption := Format('ShellIcon %dx%d', [Icon.Width, Icon.Height]); + Image1.Picture.Assign(Icon); + finally + Icon.Free; + end; +end; + +function TExampleForm1.ExecThumbnail(SizeType: TIconSizeType): Boolean; +var + Bitmap: TBitmap; +begin + Result := GetThumbnail(Bitmap, JvFilenameEdit1.FileName, GetPixels(SizeType)); + if not Result then Exit; + try + Caption := Format('Thumbnail %dx%d', [Icon.Width, Icon.Height]); + Image1.Picture.Assign(Bitmap); + finally + Bitmap.Free; + end; +end; + +function TExampleForm1.ExecFileIcon(Index: Integer; SizeType: TIconSizeType): Boolean; +var + Icon: TIcon; +begin + Result := GetFileIcon(Icon, JvFilenameEdit1.FileName, Index, GetSize(SizeType)) <> ImageSize_Non; + if not Result then Exit; + try + Caption := Format('FileIcon[%d] %dx%d', [Index, Icon.Width, Icon.Height]); + Image1.Picture.Assign(Icon); + finally + Icon.Free; + end; +end; + +function TExampleForm1.ExecSysImageListIcon(SizeType: TIconSizeType): Boolean; +var + Icon: TIcon; +begin + Result := GetSysImageListIcon(Icon, JvFilenameEdit1.FileName, SizeType); + if not Result then Exit; + try + Caption := Format('SysImageListIcon %s %dx%d', [SizeType.Id, Icon.Width, Icon.Height]); + Image1.Picture.Assign(Icon); + finally + Icon.Free; + end; +end; + +end. diff --git a/Winapi.FileThumbnail.pas b/Winapi.FileThumbnail.pas new file mode 100644 index 0000000..6e7104e --- /dev/null +++ b/Winapi.FileThumbnail.pas @@ -0,0 +1,1072 @@ +// +// File thumbnail module. +// +// Type: Windows thumbnail. +// Author: 2023 Wei-Lun Huang +// Description: Extract file thumbnail. +// +// Features: Please see the functions in interface. +// +// Last modified date: Oct 9, 2023. + + +{ Example: +uses FileThumbnail; + +procedure GetFileThumb; +var + Thumb: TFileThumb; + Icon: TIcon; +begin + if GetShellIcon(Icon, JvFilenameEdit1.FileName, _IconBest.TypicallyPixels) then + try + Image1.Picture.Assign(Icon); + finally + Icon.Free; + end + else + Image1.Picture.Assign(nil); +end; +} + +unit Winapi.FileThumbnail; + +{$IF NOT DEFINED(DEBUG)} + {$R-,Q-,V-} // RangeChecks, OverFlowChecks, VarsStringChecks + {$T-,B-,U-} // TypedAddress, BoolEval, SafeDivide + {$INLINE ON} // ON|OFF|AUTO + {$O+} // Optimization +{$ENDIF} + + +interface + +uses + Winapi.Windows, Winapi.ActiveX, Winapi.ShellApi, Winapi.commCtrl, Winapi.ShlObj, + System.SysUtils, Vcl.Graphics, + +// Necessary System.Win.ComObj.InitComObj() +// Queue CoInitializeEx into InitProc to execute when the initiation. + System.Win.ComObj; + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// +// Begin Windows API interface definition. +// + +// +// IShellItemImageFactory interface. +// +// Most of them are already defined in Winapi.ShlObj. +// +// IShellItemImageFactory::GetImage method flags. +// https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellitemimagefactory-getimage +const +// SIIGBF_RESIZETOFIT = $00000000; // Defined in Winapi.ShlObj. +// SIIGBF_BIGGERSIZEOK = $00000001; // ... +// SIIGBF_MEMORYONLY = $00000002; // ... +// SIIGBF_ICONONLY = $00000004; // ... +// SIIGBF_THUMBNAILONLY = $00000008; // ... +// SIIGBF_INCACHEONLY = $00000010; // ... + SIIGBF_CROPTOSQUARE = $00000020; + SIIGBF_WIDETHUMBNAILS = $00000040; + SIIGBF_ICONBACKGROUND = $00000080; + SIIGBF_SCALEUP = $00000100; +// End of the IShellItemImageFactory definition. + + +// +// IImageList interface. +// +// https://learn.microsoft.com/en-us/windows/win32/api/commoncontrols/nn-commoncontrols-iimagelist +const + IID_IImageList = '{46EB5926-582E-4017-9FDF-E8998DAA0950}'; +type + IImageList = interface(IUnknown) + [IID_IImageList] + function Add(Image, Mask: HBITMAP; var Index: Integer): HRESULT; stdcall; + function ReplaceIcon(IndexToReplace: Integer; Icon: HICON; var Index: Integer): HRESULT; stdcall; + function SetOverlayImage(iImage: Integer; iOverlay: Integer): HRESULT; stdcall; + function Replace(Index: Integer; Image, Mask: HBITMAP): HRESULT; stdcall; + function AddMasked(Image: HBITMAP; MaskColor: COLORREF; var Index: Integer): HRESULT; stdcall; + function Draw(var DrawParams: TImageListDrawParams): HRESULT; stdcall; + function Remove(Index: Integer): HRESULT; stdcall; + function GetIcon(Index: Integer; Flags: UINT; var Icon: HICON): HRESULT; stdcall; + function GetImageInfo(Index: Integer; var ImageInfo: TImageInfo): HRESULT; stdcall; + function Copy(iDest: Integer; SourceList: IUnknown; iSource: Integer; Flags: UINT): HRESULT; stdcall; + function Merge(i1: Integer; List2: IUnknown; i2, dx, dy: Integer; ID: TGUID; out ppvOut): HRESULT; stdcall; + function Clone(ID: TGUID; out ppvOut): HRESULT; stdcall; + function GetImageRect(Index: Integer; out rc: TRect): HRESULT; stdcall; + function GetIconSize(var cx, cy: Integer): HRESULT; stdcall; + function SetIconSize(cx, cy: Integer): HRESULT; stdcall; + function GetImageCount(var Count: Integer): HRESULT; stdcall; + function SetImageCount(NewCount: UINT): HRESULT; stdcall; + function SetBkColor(BkColor: COLORREF; var OldColor: COLORREF): HRESULT; stdcall; + function GetBkColor(var BkColor: COLORREF): HRESULT; stdcall; + function BeginDrag(iTrack, dxHotSpot, dyHotSpot: Integer): HRESULT; stdcall; + function EndDrag: HRESULT; stdcall; + function DragEnter(hWndLock: HWND; x, y: Integer): HRESULT; stdcall; + function DragLeave(hWndLock: HWND): HRESULT; stdcall; + function DragMove(x, y: Integer): HRESULT; stdcall; + function SetDragCursorImage(Image: IUnknown; iDrag, dxHotSpot, dyHotSpot: Integer): HRESULT; stdcall; + function DragShowNoLock(fShow: BOOL): HRESULT; stdcall; + function GetDragImage(var CurrentPos, HotSpot: TPoint; ID: TGUID; out ppvOut): HRESULT; stdcall; + function GetItemFlags(i: Integer; var dwFlags: DWORD): HRESULT; stdcall; + function GetOverlayImage(iOverlay: Integer; var iIndex: Integer): HRESULT; stdcall; + end; +// End of the IImageList definition. + +// End Windows API interface definition. +// +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// +// Begin function implemented. +// + +// About TIconSizeMode, see the parameter iImageList of SHGetImageList function. +// https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shgetimagelist + TIconSizeType = ( + _IconSmall, // Typically 16x16 pixels + _IconLarge, // Typically 32x32 pixels + _IconExtra, // Typically 48x48 pixels + _IconJumbo); // Typically 256x256 pixels + + TSysImageList = record +// The record will automatically handle the IImageList reference count and +// release it automatically, so Obj does not require additional processing. + Obj: IImageList; // IImageList, specify nil to release the interface. + Size: TSize; // Icon actual size. + end; + PSysImageList = ^TSysImageList; + + TSysImageLists = array[TIconSizeType] of TSysImageList; + + TIconSizeTypeHelper = record helper for TIconSizeType + protected +// These functions obtain default(const values). + function GetFlag: Integer; inline; // Read cIconTypically.iImageList + function GetId: string; inline; // Read cIconTypically.Id + function GetString: string; inline; // Read cIconTypically.Name + function GetTypicallySize: Word; inline; // Read cIconTypically.Size + function GetTypicallyPixels: TSize; // Read cIconTypically.Size and create TSize + +// Will try to call CatchImageList(TIconSizeType) to get the image size of the ImageList. + function GetSysImageList: TSysImageList; // Read gImageLists + function GetImageList: IImageList; // Read gImageLists.Obj + function GetActualPixels: TSize; // Read gImageLists.Size + public + property Flag: Integer read GetFlag; + property Id: string read GetId; + property Str: string read GetString; + property TypicallySize: Word read GetTypicallySize; + property TypicallyPixels: TSize read GetTypicallyPixels; + property SysImageList: TSysImageList read GetSysImageList; + property ImageList: IImageList read GetImageList; + property ActualPixels: TSize read GetActualPixels; + end; + + TIconSizeTypes = set of TIconSizeType; + + TImageListRetrieves = set of ( + ILR_ActualSize, // After obtaining all list of icons of sizes, choose the one with the highest actual resolution. + ILR_NoKeep, // Unkeep the interface for image lists of other sizes. + ILR_Renew); // Release the existing list and get the latest list. + + TExtractIconFlags = set of (EIF_SimulateDoc, EIF_IgnoreLarge, EIF_IgnoreSmall); + + TImageSize = (ImageSize_Non, ImageSize_Large, ImageSize_Small); + + TIconSizeInfo = record + iImageList: Integer; // This flag is parameter iImageList of SHGetImageList. + Size: Word; // Icon typically size. + Id: string; // Name defined of image list flag in Windows SDK. + Name: string; // Simple name. + end; + PIconSizeInfo = ^TIconSizeInfo; + +const + cColorDepth = 32; // Color depth, default 32. + +// TIconSizeMode + _IconBase = _IconSmall; + _IconBest = _IconJumbo; // SHIL_LAST + +// _ILR_Default: TImageListRetrieves = [ILR_ActualSize]; + +// The size is normally pixels. +// However, the icon size can be change by system setting or by user. +// when processing the CatchImageList series of functions, +// the actual size will be copied to the implementation variable gImageLists. + cIconTypically: array[TIconSizeType] of TIconSizeInfo = ( + (iImageList: SHIL_SMALL; Size: 16; ID: 'SHIL_SMALL'; Name: 'Small'), + (iImageList: SHIL_LARGE; Size: 32; ID: 'SHIL_LARGE'; Name: 'Large'), + (iImageList: SHIL_EXTRALARGE; Size: 48; ID: 'SHIL_EXTRALARGE'; Name: 'Extra'), + (iImageList: SHIL_JUMBO; Size: 256; ID: 'SHIL_JUMBO'; Name: 'Jumbo') + ); + +// Get the mode by ImageList category flag. (see value cIconTypically.iImageList). +function SysImageListFlagToIconSizeType(Flag: Integer): TIconSizeType; inline; + +// +// Get pixels of icon. +// +function GetIconTypicallySizeByFlag(out Size: Word; Flag: Integer): Boolean; overload; +function GetIconActualSizeByFlag(out Size: TSize; Flag: Integer): Boolean; overload; +function GetIconSizeByFlag(out TypicallySize: Word; out ActualSize: TSize; Flag: Integer): Boolean; overload; + +// +// Convert. +// +function ConvertToIcon(hbmColor: HBITMAP; hbmMask: HBITMAP = 0): TIcon; overload; +// If the size of the image is smaller than the specified size(ASize), +// the base of the image is expanded (not enlarged the image) and the image is centered. +function ConvertToIcon(hbmColor: HBITMAP; hbmMask: HBITMAP; ASize: TSize): TIcon; overload; + +// +// Extract thumbnail, file association icon or file icon. +// +// GetShellIcon, get image by the IShellItemImageFactory interface. (Like Windows file explorer) + +// GetShellIcon - Get the shell icon image. +function GetShellIcon(out Bitmap: HBITMAP; const AFilename: string; ASize: TSize; Flags: UINT = SIIGBF_RESIZETOFIT): Boolean; overload; +// GetShellIcon out TIcon, this is implemented with GetSysIcon out Bitmap. +function GetShellIcon(out Bitmap: TBitmap; const AFilename: string; ASize: TSize; Flags: UINT = SIIGBF_RESIZETOFIT): Boolean; overload; +function GetShellIcon(out Icon: TIcon; const AFilename: string; ASize: TSize; Flags: UINT = SIIGBF_RESIZETOFIT): Boolean; overload; + +// +// Extract thumbnail from video or image file only. +// +// GetThumbnail - Get image thumbnail of the content form video or image file. +function GetThumbnail(out Bitmap: HBITMAP; const AFilename: string; ASize: TSize; ColorDepth: DWORD = cColorDepth): Boolean; overload; +function GetThumbnail(out Bitmap: TBitmap; const AFilename: string; ASize: TSize; ColorDepth: DWORD = cColorDepth): Boolean; overload; +function GetThumbnail(out Icon: TIcon; const AFilename: string; ASize: TSize; ColorDepth: DWORD = cColorDepth): Boolean; overload; + + +// Extract file icon image only. +// +// GetFileIcon - Extract icon by index in a file. +function GetFileIcon(out Icon: HICON; const AFilename: string; Index: Integer = 0; AMaxSize: Word = 0; AMinSize: Word = 0; ExtractFlags: TExtractIconFlags = []): TImageSize; overload; +function GetFileIcon(out Icon: TIcon; const AFilename: string; Index: Integer = 0; AMaxSize: Word = 0; AMinSize: Word = 0; ExtractFlags: TExtractIconFlags = []): TImageSize; overload; +function GetFileIcon(out Bitmap: TBitmap; const AFilename: string; Index: Integer = 0; AMaxSize: Word = 0; AMinSize: Word = 0; ExtractFlags: TExtractIconFlags = []): TImageSize; overload; + +// +// Extract file association icon image only. + +// GetSysImageListIcon (Get system image list icon): +// Usually files or systems have 16 and 32 standard size icon resources. if only want to +// get 32 or 16 standard size file icons, this should be the fastest and most appropriate. +// because it is image list through the system icons cache. +// +// This is use image list of file association of system. if the size of the icon is smaller +// than the Icon size in the image list, the image will be fixed to the upper left of the Icon. +// +// Through SHGetFileInfo and SHGetImageList API's. +// So, GetSysImageListIcon will call CatchImageList to SHGetImageList to get the image list with the file association. +function GetSysImageListIcon(out Icon: HICON; const AFilename: string; SizeType: TIconSizeType = _IconBest): Boolean; overload; +function GetSysImageListIcon(out Icon: TIcon; const AFilename: string; SizeType: TIconSizeType = _IconBest): Boolean; overload; +function GetSysImageListIcon(out Bitmap: TBitmap; const AFilename: string; SizeType: TIconSizeType = _IconBest): Boolean; overload; + +// +// Check if the system image list has been obtained. +// +function SysImageListLoaded(IconSizeType: TIconSizeType): Boolean; overload; +function SysImageListLoaded: TIconSizeTypes; overload; + +// +// [Automatically] +// The following is the automatically triggered functions, no additional calls are necessary. +// + +// +// [Automatically] ImageList interface operation. +// +function GetImageListInterface(IconSizeType: TIconSizeType): IImageList; inline; +procedure FreeSysImageList(var SysImageList: TSysImageList); overload; inline; +procedure FreeSysImageList(IconSizeType: TIconSizeType); overload; +procedure FreeSysImageListAll; + +// +// [Automatically] Catch icon list of the ImageList interface from system. +// +// See the variable gImageLists and gImageListMode in implementation. +function CatchImageList(SizeType: TIconSizeType = _IconBest; ForceLatest: Boolean = False): Boolean; //overload; +function CatchImageListAll(ForceLatest: Boolean = False): TIconSizeTypes; overload; +function CatchImageListAll(out ActualBest: TIconSizeType; ForceLatest: Boolean = False): TIconSizeTypes; overload; +function CatchImageListBest(out ASysImageList: TSysImageList; Flags: TImageListRetrieves = [ILR_ActualSize]): Boolean; + +// +// [Automatically] Get ImageList form variable gImageLists in implementation. +// +function SysImageList(SizeType: TIconSizeType; ExceptNil: Boolean = True): TSysImageList; overload; +function SysImageList: TSysImageList; overload; +function SysImageLists: TSysImageLists; inline; + +implementation + +//uses +// Debug; + +var +// The TSysImageList.Obj type is an interface, +// so it cannot be used as a general variable type or a memory block filled +// with 0 (erased) when released. It needs to be specified as nil to make the +// interface automatically released. + gImageLists: array[TIconSizeType] of TSysImageList; // TSysImageList.Obj + gImageListMode: TIconSizeType = _IconBest; // IImageList size type. + + +// +// public functions +// + +function SysImageListFlagToIconSizeType(Flag: Integer): TIconSizeType; +begin + case Flag of + SHIL_LARGE : Result := _IconLarge; + SHIL_SMALL : Result := _IconSmall; + SHIL_EXTRALARGE: Result := _IconExtra; + SHIL_JUMBO : Result := _IconJumbo; + else raise Exception.Create('Invalid flag of ImageList type.');// Abort; + end; +end; + +function GetIconTypicallySizeByFlag(out Size: Word; Flag: Integer): Boolean; +var + SizeType: TIconSizeType; +begin + try + SizeType := SysImageListFlagToIconSizeType(Flag); + except + Exit(False); + end; + Size := cIconTypically[SizeType].Size; + Result := True; +end; + +function GetIconActualSizeByFlag(out Size: TSize; Flag: Integer): Boolean; +var + SizeType: TIconSizeType; +begin + try + SizeType := SysImageListFlagToIconSizeType(Flag); + except + Exit(False); + end; + Size := gImageLists[SizeType].Size; + Result := True; +end; + +function GetIconSizeByFlag(out TypicallySize: Word; out ActualSize: TSize; Flag: Integer): Boolean; +var + SizeType: TIconSizeType; +begin + try + SizeType := SysImageListFlagToIconSizeType(Flag); + except + Exit(False); + end; + TypicallySize := cIconTypically[SizeType].Size; + ActualSize := gImageLists[SizeType].Size; + Result := True; +end; + +function GetPixels(Size: TSize): Integer; +begin + if (Size.cx < Word.MinValue) or (Size.cx > Word.MaxValue) or + (Size.cy < Word.MinValue) or (Size.cy > Word.MaxValue) then + raise Exception.Create('Size exceeds range of type Word'); + Result := Size.cx * Size.cy; +end; + +function SysImageListLoaded(IconSizeType: TIconSizeType): Boolean; +begin + Result := Assigned(gImageLists[IconSizeType].Obj); +end; + +function SysImageListLoaded: TIconSizeTypes; +var + SizeType: TIconSizeType; +begin + Result := []; + for SizeType := _IconBase to _IconBest do + if Assigned(gImageLists[SizeType].Obj) then + Include(Result, SizeType); +end; + +function GetImageListInterface(IconSizeType: TIconSizeType): IImageList; +begin + if SHGetImageList(cIconTypically[IconSizeType].iImageList, IImageList, Pointer(Result)) <> S_OK then + Result := nil; +end; + +procedure FreeSysImageList(var SysImageList: TSysImageList); +begin + SysImageList.Obj := nil; + SysImageList.Size := TSize.Create(0, 0); +end; + +procedure FreeSysImageList(IconSizeType: TIconSizeType); +begin + FreeSysImageList(gImageLists[IconSizeType]); +end; + +procedure FreeSysImageListAll; +var + SizeType: TIconSizeType; +begin + for SizeType := Low(TIconSizeType) to High(TIconSizeType) do + FreeSysImageList(gImageLists[SizeType]); +end; + +function CatchImageList(SizeType: TIconSizeType; ForceLatest: Boolean): Boolean; +var + pImageList: PSysImageList; + Size: TSize; + procedure RenewSize(pItem: PSysImageList); inline; + var + N: TSize; + begin + if pItem.Obj.GetIconSize(N.cx, N.cy) = S_OK then + pItem.Size := N; + end; +begin + pImageList := @gImageLists[SizeType]; + if Assigned(pImageList.Obj) then + begin + if ForceLatest then + begin + FreeSysImageList(pImageList^); + pImageList.Obj := GetImageListInterface(SizeType); + if not Assigned(pImageList.Obj) then + Exit(False); + end + end + else + begin + pImageList.Obj := GetImageListInterface(SizeType); + if not Assigned(pImageList.Obj) then + Exit(False); + end; + + if ForceLatest then + begin + RenewSize(pImageList); + Exit(True); + end; + + Size := pImageList.Size; + if (Size.cx <= 0) or (Size.cy <= 0) then + RenewSize(pImageList); + Result := True; +end; + +function CatchImageListAll(ForceLatest: Boolean): TIconSizeTypes; +var + SizeType: TIconSizeType; +begin + Result := []; + for SizeType := _IconBest downto _IconBase do + if CatchImageList(SizeType, ForceLatest) then + Include(Result, SizeType); +end; + +function CatchImageListAll(out ActualBest: TIconSizeType; ForceLatest: Boolean): TIconSizeTypes; +var + SizeType: TIconSizeType; + Size, LastSize: TSize; +begin + Result := []; + LastSize := TSize.Create(0, 0); + for SizeType := _IconBest downto _IconBase do + begin + if not CatchImageList(SizeType, ForceLatest) then + Continue; + + Size := gImageLists[SizeType].Size; + if GetPixels(Size) > GetPixels(LastSize) then + ActualBest := SizeType; + LastSize := Size; + + Include(Result, SizeType); + end; + + if (LastSize.cx > 0) and (LastSize.cy > 0) then + Exit; + + for SizeType := _IconBest downto _IconBase do + if SizeType in Result then + begin + ActualBest := SizeType; + Break; + end; +end; + + + +function CatchImageListBest(out ASysImageList: TSysImageList; Flags: TImageListRetrieves): Boolean; +var + SizeType: TIconSizeType; +begin + gImageListMode := _IconBest; + if ILR_ActualSize in Flags then + begin + if CatchImageListAll(gImageListMode, ILR_Renew in Flags) = [] then + Exit(False); + if ILR_NoKeep in Flags then + for SizeType := Low(TIconSizeType) to High(TIconSizeType) do + if SizeType <> gImageListMode then + FreeSysImageList(SizeType); + Result := True; + end + else + begin + Result := CatchImageList(_IconBest, ILR_Renew in Flags); + if not Result then + Exit(False); + end; + ASysImageList := gImageLists[gImageListMode]; +end; + +function SysImageList(SizeType: TIconSizeType; ExceptNil: Boolean): TSysImageList; +begin + if (SizeType < Low(TIconSizeType)) or (SizeType > High(TIconSizeType)) then + raise Exception.Create('Out of index.'); + + Result := gImageLists[SizeType]; + + if not Assigned(Result.Obj) and ExceptNil then + raise Exception.Create('ImageList does not exist.'); +end; + +function SysImageList: TSysImageList; +begin + Result := SysImageList(gImageListMode); +end; + +function SysImageLists: TSysImageLists; +var + SizeType: TIconSizeType; +begin + for SizeType := Low(TIconSizeType) to High(TIconSizeType) do + Result[SizeType] := SysImageList(SizeType); +end; + + +function ConvertToIcon(hbmColor: HBITMAP; hbmMask: HBITMAP): TIcon; +var + IconInfo: TIconInfo; + Icon: HICON; + DIB: TDIBSection; + Mask: TBitmap; +begin +// English: +// Regarding the DestroyIcon, CreateIconIndirect, and the TIcon.Handle property: +// Internal process of TIcon.Handle property setting: +// TIcon.Handle property >> TIcon.SetHandle function >> TIcon.NewImage function >> +// Replaces TIcon.FImage by creating a new TIconImage with the value specified by TIconImage.FHandle. +// When TIcon is destroyed, TIcon.FImage.Release will be executed, which will +// trigger DestroyIcon to release the value specified by TIcon.Handle. +// Therefore, the HICON set by TIcon.Handle will be released when the TIcon is released, +// without the need for an additional DestroyIcon. +// 中文: +// 關於 CreateIconIndirect 相應的 DestroyIcon,與 TIcon.Handle 屬性設定: +// TIcon.Handle 屬性設定的內部流程: +// TIcon.Handle >> TIcon.SetHandle >> TIcon.NewImage >> +// 取代 TIcon.FImage 為建立新的 TIconImage 且該 TIconImage.FHandle 為 TIcon.Handle 指定的值。 +// 當 TIcon 進行摧毀時會執行 TIcon.FImage.Release,進而引發 DestroyIcon 來釋放 TIcon.Handle 指定的值。 +// 因此,TIcon.Handle 設定的 HICON 會在 TIcon 釋放時一並釋放,不必額外 DestroyIcon。 + + +// see ICONINFO structure +// https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-iconinfo + IconInfo.fIcon := True; // True 表示輸出 Icon,False 表示輸出 Cursor + IconInfo.xHotspot := 0; // Icon 則不需要,如 Cursor 則水平中心點 + IconInfo.yHotspot := 0; // Icon 則不需要,如 Cursor 則垂直中心點 + if hbmMask <> 0 then + begin // Create an Icon with a specified mask. + IconInfo.hbmMask := hbmMask; + IconInfo.hbmColor := hbmColor; + Icon := CreateIconIndirect(IconInfo); + if Icon = 0 then + Exit(nil); + + Result := TIcon.Create; + Result.Handle := Icon; + Exit; + end; + + FillChar(DIB, SizeOf(DIB), 0); + // Get Bitmap image information. + if GetObject(hbmColor, SizeOf(DIB), @DIB) = 0 then + Exit(nil); + + // Create a new mask image. + Mask := TBitmap.Create(DIB.dsBm.bmWidth, DIB.dsBm.bmHeight); + try + Mask.Monochrome := True; + + // + // Draw a rectangular mask image with the bmColor image size. + // + Mask.Canvas.Lock; + try + Mask.Canvas.Brush.Color := clBlack; + Mask.Canvas.FillRect(TRect.Create(0, 0, DIB.dsBm.bmWidth, DIB.dsBm.bmHeight)); + finally + Mask.Canvas.Unlock; + end; + + // + // Create an Icon with a new mask. + // + IconInfo.hbmMask := Mask.Handle; + IconInfo.hbmColor := hbmColor; + Icon := CreateIconIndirect(IconInfo); + if Icon = 0 then + Exit(nil); + + Result := TIcon.Create; + Result.Handle := Icon; + finally + Mask.Free; + end; +end; + +function ConvertToIcon(hbmColor: HBITMAP; hbmMask: HBITMAP; ASize: TSize): TIcon; +var + bSize: Boolean; + Size: TSize; + Bmp, BmpColor, BmpMask: TBitmap; + Point: TPoint; +begin + if ASize.IsZero then + Exit(ConvertToIcon(hbmColor, hbmMask)); + + Bmp := TBitmap.Create; + try + Bmp.Handle := hbmColor; + + // + // Checks whether the size is less than the specified size.(meaning, ASize is minimum size) + // + bSize := False; + if ASize.Width < Bmp.Width then + Size.cx := Bmp.Width + else + begin + bSize := True; + Size.cx := ASize.Width + end; + if ASize.Height < Bmp.Height then + Size.cy := Bmp.Height + else + begin + bSize := True; + Size.cy := ASize.Height; + end; + + if not bSize then + begin // Create Icon at original size. + Exit(ConvertToIcon(hbmColor, hbmMask)); + end; + + Point := TPoint.Create((Size.cx - Bmp.Width) shr 1, (Size.cy - Bmp.Height) shr 1); + + BmpColor := TBitmap.Create; + try + BmpColor.Assign(Bmp); + // Copy the image of TBitmap.Handle and disassociate it from the + // system handle to make the hBitmap image content independent. + BmpColor.HandleType := bmDDB; + + BmpColor.Palette := Bmp.Palette; + BmpColor.SetSize(Size.cx, Size.cy); + BmpColor.Canvas.Lock; + try + if BmpColor.Transparent and (BmpColor.TransparentMode = tmFixed) then + BmpColor.Canvas.Brush.Color := Bmp.TransparentColor + else + BmpColor.Canvas.Brush.Color := clDefault; + BmpColor.Canvas.FillRect(TRect.Create(0, 0, BmpColor.Width, BmpColor.Height)); + BmpColor.Canvas.Draw((Size.cx - Bmp.Width) shr 1, (Size.cy - Bmp.Height) shr 1, Bmp); + finally + BmpColor.Canvas.Unlock; + end; + + if hbmMask = 0 then + begin // Creates the Icon by a mask at the new size. + BmpMask := TBitmap.Create(Size.cx, Size.cy); + try + // Set a mask image by the BmpColor image. + BmpMask.Handle := BmpColor.MaskHandle; + + // Copy the image of TBitmap.Handle and disassociate it from the + // system handle to make the hBitmap image content independent. + BmpMask.HandleType := bmDDB; + + BmpMask.Monochrome := True; // Convert the image to single color. + + // + // Fill the base + // + BmpMask.Canvas.Lock; + try + BmpMask.Canvas.Brush.Color := clBlack; + BmpMask.Canvas.FillRect(TRect.Create(Point.X, Point.Y, Point.X + Bmp.Width, Point.Y + Bmp.Height)); + finally + BmpMask.Canvas.Unlock; + end; + + // Create Icon by new mask. + Result := ConvertToIcon(BmpColor.Handle, BmpMask.Handle); + finally + BmpMask.Free; + end; + end + else + begin // Create the Icon by a mask by enlarging the base of the old mask with the new size.. + // 尚未測試 + Bmp.Handle := hbmMask; + BmpMask := TBitmap.Create; + try + // Copy old mask image. + BmpMask.Assign(Bmp); + + // Content copied via TBitmap.Assign still maintains the association (DIB), + // so... + // Copy the image of TBitmap.Handle and disassociate it from the + // system handle to make the hBitmap image content independent. + BmpMask.HandleType := bmDDB; + + BmpMask.Palette := Bmp.Palette; + BmpMask.SetSize(Size.cx, Size.cy); + BmpMask.Monochrome := True; + + // + // Fill the base then copy the old mask image to new mask image. + // + BmpMask.Canvas.Lock; + try + BmpMask.Canvas.Brush.Color := clWhite; + BmpMask.Canvas.FillRect(TRect.Create(0, 0, BmpMask.Width, BmpMask.Height)); + BmpMask.Canvas.Draw((Size.cx - Bmp.Width) shr 1, (Size.cy - Bmp.Height) shr 1, Bmp); + finally + BmpMask.Canvas.Unlock; + end; + + // Create Icon by new mask. + Result := ConvertToIcon(BmpColor.Handle, BmpMask.Handle); + finally + BmpMask.Free; + end; + end; + finally + BmpColor.Free; + end; + finally + Bmp.Free; + end; +end; + +function GetShellIcon(out Bitmap: HBITMAP; const AFilename: string; ASize: TSize; Flags: UINT): Boolean; +var + ImageFactory: IShellItemImageFactory; +begin + if SHCreateItemFromParsingName(PChar(AFilename), nil, IShellItemImageFactory, ImageFactory) = S_OK then + Exit(ImageFactory.GetImage(ASize, Flags, Bitmap) = S_OK); + Result := False; +end; + +function GetShellIcon(out Bitmap: TBitmap; const AFilename: string; ASize: TSize; Flags: UINT): Boolean; +var + hBmp: HBITMAP; +begin + Result := GetShellIcon(hBmp, AFilename, ASize, Flags); + if not Result then + Exit; + Bitmap := TBitmap.Create; + Bitmap.TransparentMode := tmAuto; + Bitmap.Handle := hBmp; +end; + +function GetShellIcon(out Icon: TIcon; const AFilename: string; ASize: TSize; Flags: UINT): Boolean; +var + Bitmap: HBITMAP; +begin + Result := GetShellIcon(Bitmap, AFilename, ASize, Flags); + if Result then + Icon := ConvertToIcon(Bitmap, 0, ASize); +end; + +function GetThumbnail(out Bitmap: HBITMAP; const AFilename: string; ASize: TSize; ColorDepth: DWORD): Boolean; +type + TBufferISF = record // For ISF parameter buffer. + pItemIDL: PItemIDList; + Attrib: DWORD; + Eaten: DWORD; + end; + TBufferLocation = record // For IExtractImage::GetLocation parameter buffer. + GLResult: HResult; + Size: TSize; + Flags: Cardinal; + Priority: Cardinal; + end; + TBufferMultiple = record // Merge the parameter buffer spaces. + case Integer of + 0: (ISF: TBufferISF); + 1: (IGL: TBufferLocation); + end; +var + Path, Name: String; + DesktopISF, FolderISF: IShellFolder; + IExtractImg: IExtractImage; + Buff: TBufferMultiple; + CharBuf: array[0..MAX_PATH] of WideChar; // Originally it was 0..2047. +// MemAlloc: IMalloc; +begin + Result := False; + + Path := ExtractFilePath(AFilename); + Name := ExtractFileName(AFilename); + if Name.IsEmpty then + Exit; + +// if (SHGetMalloc(MemAlloc) <> NOERROR) or (MemAlloc = nil) or +// (NOERROR <> SHGetDesktopFolder(DesktopISF)) then +// Exit; + + if SHGetDesktopFolder(DesktopISF) <> S_OK then + Exit; + try + if DesktopISF.ParseDisplayName(0, nil, PChar(Path), Buff.ISF.Eaten, Buff.ISF.pItemIDL, Buff.ISF.Attrib) <> S_OK then + Exit; + try + if DesktopISF.BindToObject(Buff.ISF.pItemIDL, nil, IShellFolder, FolderISF) <> S_OK then + Exit; + finally + CoTaskMemFree(Buff.ISF.pItemIDL); + end; + if FolderISF.ParseDisplayName(0, nil, PChar(Name), Buff.ISF.Eaten, Buff.ISF.pItemIDL, Buff.ISF.Attrib) <> S_OK then + Exit; + try + if FolderISF.GetUIObjectOf(0, 1, Buff.ISF.pItemIDL, IExtractImage, nil, IExtractImg) <> S_OK then + Exit; + finally + CoTaskMemFree(Buff.ISF.pItemIDL); + end; + finally + FolderISF := nil; + DesktopISF := nil; + end; + if not Assigned(IExtractImg) then + Exit; + try +// FillChar(CharBuf, SizeOf(CharBuf), 0); + Buff.IGL.Size := ASize; + Buff.IGL.Priority := ITSAT_MIN_PRIORITY; + Buff.IGL.Flags := IEIFLAG_SCREEN or IEIFLAG_OFFLINE or IEIFLAG_QUALITY; + + // IExtractImage::Extract must call IExtractImage::GetLocation prior to calling Extract. + Buff.IGL.GLResult := IExtractImg.GetLocation(CharBuf, SizeOf(CharBuf), Buff.IGL.Priority, Buff.IGL.Size, ColorDepth, Buff.IGL.Flags); + if Buff.IGL.GLResult <> NOERROR then + Exit; + + if IExtractImg.Extract(Bitmap) = NOERROR then + Result := Bitmap <> 0 + else + Result := False; + finally + IExtractImg := nil; + end; +end; + +function GetThumbnail(out Bitmap: TBitmap; const AFilename: string; ASize: TSize; ColorDepth: DWORD): Boolean; +var + hBmp: HBITMAP; +begin + Result := GetThumbnail(hBmp, AFilename, ASize, ColorDepth); + if not Result then + Exit; + Bitmap := TBitmap.Create; + Bitmap.Handle := hBmp; +end; + +function GetThumbnail(out Icon: TIcon; const AFilename: string; ASize: TSize; ColorDepth: DWORD): Boolean; +var + hBmp: HBITMAP; +begin + Result := GetThumbnail(hBmp, AFilename, ASize, ColorDepth); + if Result then + Icon := ConvertToIcon(hBmp, 0, ASize); +end; + +function GetFileIcon(out Icon: HICON; const AFilename: string; Index: Integer; AMaxSize: Word; AMinSize: Word; ExtractFlags: TExtractIconFlags): TImageSize; +var + Flags: UINT; + hLargeIcon, hSmallIcon: HICON; +begin + Result := ImageSize_Non; + if EIF_SimulateDoc in ExtractFlags then + Flags := GIL_SIMULATEDOC + else + Flags := 0; + hLargeIcon := 0; + hSmallIcon := 0; + try + if SHDefExtractIcon(PChar(AFilename), Index, Flags, hLargeIcon, hSmallIcon, AMinSize shl 16 or AMaxSize) <> S_OK then + Exit; + if not(EIF_IgnoreLarge in ExtractFlags) and (hLargeIcon <> 0) then + begin + Icon := hLargeIcon; + hLargeIcon := 0; + Exit(ImageSize_Large); + end; + if not(EIF_IgnoreSmall in ExtractFlags) and (hSmallIcon <> 0) then + begin + Icon := hSmallIcon; + hSmallIcon := 0; + Exit(ImageSize_Small); + end; + finally + if hLargeIcon <> 0 then + DestroyIcon(hLargeIcon); + if hSmallIcon <> 0 then + DestroyIcon(hSmallIcon); + end; +end; + +function GetFileIcon(out Icon: TIcon; const AFilename: string; Index: Integer; AMaxSize: Word; AMinSize: Word; ExtractFlags: TExtractIconFlags): TImageSize; +var + IconHandle: HIcon; +begin + Result := GetFileIcon(IconHandle, AFilename, Index, AMaxSize, AMinSize, ExtractFlags); + if Result = ImageSize_Non then + Exit; + Icon := TIcon.Create; + Icon.Handle := IconHandle; +end; + +function GetFileIcon(out Bitmap: TBitmap; const AFilename: string; Index: Integer; AMaxSize: Word; AMinSize: Word; ExtractFlags: TExtractIconFlags): TImageSize; +var + Icon: TIcon; +begin + Result := GetFileIcon(Icon, AFilename, Index, AMaxSize, AMinSize, ExtractFlags); + if Result = ImageSize_Non then + Exit; + try + Bitmap := TBitmap.Create; + Bitmap.Assign(Icon); + finally + Icon.Free; + end; +end; + +function GetSysImageListIcon(out Icon: HICON; const AFilename: string; SizeType: TIconSizeType): Boolean; +var + ShInfo: TShFileInfo; + GFIResult: IImageList; +begin + Result := False; + if not CatchImageList(SizeType, False) then + Exit; + + GFIResult := IImageList(SHGetFileInfo(PChar(AFilename), FILE_ATTRIBUTE_NORMAL, + ShInfo, SizeOf(ShInfo), SHGFI_SYSICONINDEX)); + if GFIResult = nil then + Exit; + + ShInfo.hIcon := 0; + if SysImageList(SizeType).Obj.GetIcon(ShInfo.iIcon, ILD_PRESERVEALPHA, ShInfo.hIcon) <> S_OK then + Exit; + if ShInfo.hIcon = 0 then + Exit; + + Icon := ShInfo.hIcon; + Result := True; +end; + +function GetSysImageListIcon(out Icon: TIcon; const AFilename: string; SizeType: TIconSizeType): Boolean; +var + h: HICON; +begin + Result := GetSysImageListIcon(h, AFilename, SizeType); + if not Result then + Exit; + Icon := TIcon.Create; + Icon.Handle := h; +end; + +function GetSysImageListIcon(out Bitmap: TBitmap; const AFilename: string; SizeType: TIconSizeType): Boolean; +var + Icon: TIcon; +begin + Result := GetSysImageListIcon(Icon, AFilename, SizeType); + if not Result then + Exit; + try + Bitmap := TBitmap.Create; + Bitmap.Assign(Icon); + finally + Icon.Free; + end; +end; + +{ TIconSizeModeHelper } + +function TIconSizeTypeHelper.GetFlag: Integer; +begin + Result := cIconTypically[Self].iImageList; +end; + +function TIconSizeTypeHelper.GetId: string; +begin + Result := cIconTypically[Self].Id; +end; + +function TIconSizeTypeHelper.GetString: string; +begin + Result := cIconTypically[Self].Name; +end; + +function TIconSizeTypeHelper.GetTypicallySize: Word; +begin + Result := cIconTypically[Self].Size; +end; + +function TIconSizeTypeHelper.GetTypicallyPixels: TSize; +var + N: Word; +begin + N := GetTypicallySize; + Result := TSize.Create(N, N); +end; + +function TIconSizeTypeHelper.GetSysImageList: TSysImageList; +begin + CatchImageList(Self, False); + Result := gImageLists[Self]; +end; + +function TIconSizeTypeHelper.GetImageList: IImageList; +begin + CatchImageList(Self, False); + Result := gImageLists[Self].Obj; +end; + +function TIconSizeTypeHelper.GetActualPixels: TSize; +begin + CatchImageList(Self, False); + Result := gImageLists[Self].Size; +end; + +initialization + FillChar(gImageLists, SizeOf(gImageLists), 0); + +finalization + FreeSysImageListAll; + +end.