Jump to content

This site uses cookies. By continuing to browse the site you are agreeing to our use of cookies. Find out more here. X
X


Photo

HICON to .ico file


  • Please log in to reply
30 replies to this topic

#1 smashly

smashly

  • Active Members
  • PipPipPipPipPipPip
  • 1,636 posts

Posted 25 August 2009 - 06:54 AM

Hi,

Edit Again: I used GetBitmapBits instead of _WinAPI_GetDIBits() to retrieve the dib bits.
Tried it in XP x86, Tried it in Win7 x64 using x64 & x86 autoit.
And it works ok for me....
Posted Image
Excuse the crude code below..
But I was curious on how to create a .ico file from a HICON
This was my untidy attempt..lol
AutoIt         
#include <GDIPlus.au3> #include <WinAPI.au3> Opt("MustDeclareVars", 1) Global $sRegPath, $sImagePath, $hImage, $hIcon ; Get the path of the image $sRegPath = "HKLM\SOFTWARE\AutoIt v3\AutoIt" If StringInStr("X64IA64", @OSArch) Then $sRegPath = StringReplace($sRegPath, "SOFTWARE", "SOFTWARE\Wow6432Node") $sImagePath = RegRead($sRegPath, "InstallDir") & "\Examples\GUI\logo4.gif" ; Start GDIPlus _GDIPlus_Startup() ; Load image $hImage = _GDIPlus_ImageLoadFromFile($sImagePath) ; Create a HICON from the image, ; Before doing this you should really scale your image to an icon size! ; But I just wanted to show that it works..lol $hIcon = _GDIPlus_BitmapCreateHICONFromBitmap($hImage) ;Clean up and shutdown GDIPlus _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() ; Create an ico file from the image _CreateIconFileFromHICON($hIcon, @ScriptDir & "\NewAutoit.ico") ; Destroy the HICON now I've finished with it. _WinAPI_DestroyIcon($hIcon) Func _CreateIconFileFromHICON($hIcon, $sOutIcon)     Local $aInfo, $sIco, $sBmp, $hCDC, $tBI, $tBits, $iSz, $sBD, $FO     ; Start of single Icon Header 3 x 2 bytes = 6 bytes: 0000 Reserved / 0100 Icon / 0100 Numer of icons, total length will be 22 bytes for a single icon when finished     $sIco = "0x000001000100"     ; Start of the Bitmap data header 1 x 4bytes: length of the header will be 40 bytes when finished. Will be appended to the end of the icon header when finished     $sBmp = "28000000"     ; Get info about the HICON, this is mainly to get the pointers to the Color/Mask bitmaps data     $aInfo = _WinAPI_GetIconInfo($hIcon)     ; Create a memory Compatable DC     $hCDC = _WinAPI_CreateCompatibleDC(0)     ; Create a BITMAPINFO Struct to store the Bitmap Info, it needs to be inilialized by setting the struct size.     $tBI = DllStructCreate($tagBITMAPINFO)     DllStructSetData($tBI, "Size", DllStructGetSize($tBI))     ; Pass a bitmap data pointer to the BITMAPINFO struct so we can recieve the details of the color bitmap data, we use it to write the headers     _WinAPI_GetDIBits($hCDC, $aInfo[5], 0, 0, 0, DllStructGetPtr($tBI), 0)     ; Now we have some the basic info to add to the Icon & Bitmap header so we'll add that to the headers.     $sIco &= Hex(DllStructGetData($tBI, "Width"), 2) & Hex(DllStructGetData($tBI, "Height"), 2) & "00000100" & _RB(Hex(DllStructGetData($tBI, "BitCount"), 4))     $sBmp &= _RB(Hex(DllStructGetData($tBI, "Width"))) & _RB(Hex(DllStructGetData($tBI, "Height") * 2)) & "0100" & _RB(Hex(DllStructGetData($tBI, "BitCount"), 4)) & "00000000"     ; Get the size of the Bitmap data from the BITMAPINFO Struct, we'll use this in the headers further on.     $iSz = DllStructGetData($tBI, "SizeImage")     ; Create a struct to store the Bitmap data Bits of the first bitmap, reset the BITMAPINFO struct     $tBits = DllStructCreate("byte[" & DllStructGetData($tBI, "SizeImage") & "]")     ; Get the color bitmap dib bits into the $tBits struct.     DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $aInfo[5], 'int', $iSz, 'ptr', DllStructGetPtr($tBits))     ; Get GetBitmapBits returns Bottom to Top dib, so I turn it to Top to Bottom dib ;)     ; ATM I'm only assuming that GetBitmapBits returns a Bottom to Top dib, maybe the bitmap bits you use could be Top Down already?.     For $i = DllStructGetData($tBI, "SizeImage") + 1 To 0 Step -(DllStructGetData($tBI, "SizeImage") / DllStructGetData($tBI, "Height"))         $sBD &= StringTrimLeft(BinaryMid(DllStructGetData($tBits, 1), $i, (DllStructGetData($tBI, "SizeImage") / DllStructGetData($tBI, "Height"))), 2)     Next     ;Clear the BITMAPINFO & $tBits Struct as we'll use the same variables again for the mask bitmap data     $tBits = 0     $tBI = 0     ; Create a BITMAPINFO Struct to store the Bitmap Info again, it needs to be inilialized by setting the struct size.     $tBI = DllStructCreate($tagBITMAPINFO)     DllStructSetData($tBI, "Size", DllStructGetSize($tBI))     ; Pass a bitmap data pointer to the BITMAPINFO struct so we can recieve the details of the bitmask bitmap data     _WinAPI_GetDIBits($hCDC, $aInfo[4], 0, 0, 0, DllStructGetPtr($tBI), 0)     ; We've finished with the Compatable DC, delete it.     _WinAPI_DeleteDC($hCDC)     ; Add the size of the of the color + bitmask bitmap data as we need this for both the Icon & Bitmap header     $iSz += DllStructGetData($tBI, "SizeImage")     ; combine the bitmap data size with the bitmap header, I'm padding the rest of the 40 byte bitmap header with 0's., that's the Bitmap header done     $sBmp &= _RB(Hex($iSz)) & "00000000000000000000000000000000"     ; Now add the size of the Bitmap data + bitmap header size and combine the icon header together with the bitmap header and color bitmap data     $sIco &= _RB(Hex($iSz + 40)) & _RB(Hex("22")) & $sBmp & $sBD     ; Create a struct to store the Bitmap dib Bits of the mask bitmap     $tBits = DllStructCreate("byte[" & DllStructGetData($tBI, "SizeImage") & "]")     ; Get the mask bitmap dib bits into the $tBits struct.     DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $aInfo[4], 'int', DllStructGetData($tBI, "SizeImage"), 'ptr', DllStructGetPtr($tBits))     ; Get GetBitmapBits returns Bottom to Top dib, so I turn it to a Top to Bottom dib and append the mask bitmap data to the icon     For $i = DllStructGetData($tBI, "SizeImage") + 1 To 0 Step -(DllStructGetData($tBI, "SizeImage") / DllStructGetData($tBI, "Height"))         $sIco &= StringTrimLeft(BinaryMid(DllStructGetData($tBits, 1), $i, (DllStructGetData($tBI, "SizeImage") / DllStructGetData($tBI, "Height"))), 2)     Next     ; Write the icon to a file.     $FO = FileOpen($sOutIcon, 18)     FileWrite($sOutIcon, Binary($sIco))     FileClose($FO)     ; Clear the structs     $tBits = 0     $tBI = 0 EndFunc   ;==>_CreateIconFileFromHICON ; Reverse Byte String Func _RB($sByte)     Local $aX = StringRegExp($sByte, "(.{2})", 3), $sX = ''     For $i = UBound($aX) - 1 To 0 Step -1         $sX &= $aX[$i]     Next     Return $sX EndFunc   ;==>_RB Func _GDIPlus_BitmapCreateHICONFromBitmap($hBitmap)     Local $hIcon     $hIcon = DllCall($ghGDIPDll, "int", "GdipCreateHICONFromBitmap", "hwnd", $hBitmap, "int*", 0)     If @error Then Return SetError(@error, 0, -1)     Return SetError($hIcon[0], 0, $hIcon[2]) EndFunc   ;==>_GDIPlus_BitmapCreateHICONFromBitmap

If a user is wanting to use an already prepared 256x256 png then this function is not for you as your icon size will be huge..
Your better off writing the icon header and append the the png strait after the header, no get dib bits and your icon will only be 22bytes larger then the png.


Cheers

Edited by smashly, 26 August 2009 - 04:39 AM.








#2 UEZ

UEZ

    Never say never

  • MVPs
  • 5,079 posts

Posted 25 August 2009 - 07:26 AM

AutoIt is crashing when I execute the script >_<

Probably this line
_WinAPI_GetDIBits($hCDC, $aInfo[5], 0, DLLStructGetData($tBI, "Height"), DllStructGetPtr($tBits), DllStructGetPtr($tBI), 0)
in function Func _CreateIconFileFromHICON($hIcon, $sOutIcon) is causing the crash!?!

I'm using Vista x32 and AutoIt v3.3.0.0 / AutoIt v3.3.1.1 Beta.

UEZ

Edited by UEZ, 25 August 2009 - 07:37 AM.

 
The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯


#3 Yashied

Yashied

    Happy in Moscow

  • MVPs
  • 2,587 posts

Posted 25 August 2009 - 07:59 AM

For me too.

#4 smashly

smashly

  • Active Members
  • PipPipPipPipPipPip
  • 1,636 posts

Posted 25 August 2009 - 11:15 AM

Sorry but I can't see why your getting crash..
I'm using Win7 x64 / AutoIt v3.3.0.0 / AutoIt v3.3.1.1 Beta.

This is the output I get in scite console when the script is run
>"C:\Program Files (x86)\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /beta /ErrorStdOut /in "C:\AutoIt\IcoFileFromHICON\IcoFromHicon.au3" /autoit3dir "C:\Program Files (x86)\AutoIt3\beta" /UserParams     +>21:11:57 Starting AutoIt3Wrapper v.2.0.0.1    Environment(Language:0409  Keyboard:00000409  OS:WIN_VISTA/  CPU:X64 OS:X64) >Running AU3Check (1.54.16.0)  from:C:\Program Files (x86)\AutoIt3\beta +>21:11:57 AU3Check ended.rc:0 >Running:(3.3.1.1):C:\Program Files (x86)\AutoIt3\beta\autoit3_x64.exe "C:\AutoIt\IcoFileFromHICON\IcoFromHicon.au3"     +>21:11:57 AutoIT3.exe ended.rc:0 +>21:11:58 AutoIt3Wrapper Finished >Exit code: 0    Time: 1.854



I'll have a look at it on a x86 platform when I get a chance..
PS. that return is using the code copied from the first post.

Edit: had a look at the code under x86.. Seems to be the _WinAPI_ReleaseDC(0,$hDC) has to moved to the end of the function.
Updated first post..

Edited by smashly, 25 August 2009 - 11:38 AM.


#5 UEZ

UEZ

    Never say never

  • MVPs
  • 5,079 posts

Posted 25 August 2009 - 11:41 AM

Ok, I tested it on my vm (environment: Win2k3 Standard x64 SP2):

 
>"C:\Program Files (x86)\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /prod /ErrorStdOut /in "E:\AU3\Test01.au3" /autoit3dir "C:\Program Files\AutoIt3" /UserParams
+>13:29:19 Starting AutoIt3Wrapper v.2.0.0.0 Environment(Language:0409 Keyboard:00000407 OS:WIN_2003/Service Pack 2 CPU:X64)
>Running AU3Check (1.54.14.0) from:C:\Program Files (x86)\AutoIt3
+>13:29:19 AU3Check ended.rc:0
>Running:(3.3.0.0):C:\Program Files (x86)\AutoIt3\autoit3.exe "E:\AU3\Test01.au3"
!>13:29:22 AutoIT3.exe ended.rc:-1073741819
+>13:29:23 AutoIt3Wrapper Finished
>Exit code: -1073741819 Time: 4.947

 


UEZ

 
The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯


#6 smashly

smashly

  • Active Members
  • PipPipPipPipPipPip
  • 1,636 posts

Posted 25 August 2009 - 11:57 AM

Ok, I tested it on my vm (environment: Win2k3 Standard x64 SP2):

 
>"C:\Program Files (x86)\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /prod /ErrorStdOut /in "E:\AU3\Test01.au3" /autoit3dir "C:\Program Files\AutoIt3" /UserParams
+>13:29:19 Starting AutoIt3Wrapper v.2.0.0.0 Environment(Language:0409 Keyboard:00000407 OS:WIN_2003/Service Pack 2 CPU:X64)
>Running AU3Check (1.54.14.0) from:C:\Program Files (x86)\AutoIt3
+>13:29:19 AU3Check ended.rc:0
>Running:(3.3.0.0):C:\Program Files (x86)\AutoIt3\autoit3.exe "E:\AU3\Test01.au3"
!>13:29:22 AutoIT3.exe ended.rc:-1073741819
+>13:29:23 AutoIt3Wrapper Finished
>Exit code: -1073741819 Time: 4.947

 


UEZ

Did you try it with updated first post?
It works for me now x86 or x64 autoit 3.3.0.0 or beta 3.3.1.1 ...
Have you tried it under x64 autoit?
Cause your return tells me x86 autoit was used, but it still shouldn't matter..

>Running:(3.3.0.0):C:\Program Files (x86)\AutoIt3\autoit3.exe "E:\AU3\Test01.au3"



#7 UEZ

UEZ

    Never say never

  • MVPs
  • 5,079 posts

Posted 25 August 2009 - 12:21 PM

Mmmhhhh, strange >_<:

when I add #AutoIt3Wrapper_UseX64=y, compile it and run the exe afterwards then it creates the NewAutoIt.ico (no em during the compilation)!

But when I start the script by F5 it gives me following error:

 
>"C:\Program Files (x86)\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /prod /ErrorStdOut /in "E:\AU3\Test01.au3" /autoit3dir "C:\Program Files\AutoIt3" /UserParams
+>14:10:16 Starting AutoIt3Wrapper v.2.0.0.0 Environment(Language:0409 Keyboard:00000407 OS:WIN_2003/Service Pack 2 CPU:X64)
>Running AU3Check (1.54.14.0) from:C:\Program Files (x86)\AutoIt3
+>14:10:16 AU3Check ended.rc:0
>Running:(3.3.0.0):C:\Program Files (x86)\AutoIt3\autoit3.exe "E:\AU3\Test01.au3"
E:\AU3\Test01.au3 (95) : ==> Variable used without being declared.:
_WinAPI_GetDIBits($hCDC, $aInfo[4], 0, DLLStructGetData($tBI, "Height"), DllStructGetPtr($tBits), DllStructGetPtr($tBI), 0)
_WinAPI_GetDIBits(^ ERROR
->14:10:16 AutoIT3.exe ended.rc:1
+>14:10:18 AutoIt3Wrapper Finished
>Exit code: 1 Time: 2.096

 

When I move the line Local $aInfo, $sIco, $sBmp, $hDC, $hCDC, $tBI, $tBits, $iSz, $sBD and start it by pressing F5 it shows the em in my previous post
(!>14:18:02 AutoIT3.exe ended.rc:-1073741819)


UEZ

 
The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯


#8 smashly

smashly

  • Active Members
  • PipPipPipPipPipPip
  • 1,636 posts

Posted 26 August 2009 - 02:06 AM

Updated first post..
Hopefully x86 users will get some joy.. fingers crossed..lol

Changed the method to get the dib bits, should work on x86 and x64 AutoIt/OS.

Strange that x86 Autoit on x86 OS fails the 2nd call to _WinAPI_GetDIBits() to retrieve the dib bits..
By all rights it should work.. I thought it may be a memory prob with the ptr for the tBits struct.. but it's not.
But no matter what I tried the 2nd call _WinAPI_GetDIBits() to retrieve the dib bits fails with an autoit crash on x86 Autoit/OS.
I also thought that maybe the image I was passing was not in the correct format or the Compatible DC part is wrong..
But if that was the case the it would fail on the 1st pass when when filling the BITMAPINFO struct
I must be missing or doing something wrong when passing the ptr..

Yet it succeeds on x64 AutoIt/OS fine.. >_<

Oh well, live and learn...

#9 UEZ

UEZ

    Never say never

  • MVPs
  • 5,079 posts

Posted 26 August 2009 - 07:03 AM

It's working now on my system >_<


UEZ

 
The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯


#10 Yashied

Yashied

    Happy in Moscow

  • MVPs
  • 2,587 posts

Posted 26 August 2009 - 08:12 AM

Works for me too. Thanks.

#11 Iuli

Iuli

    Adventurer

  • Active Members
  • PipPip
  • 127 posts

Posted 27 August 2009 - 12:10 PM

Very useful >_< Thanks for code.
Posted Image SFXMaker - The most complete switchless installer creator software

#12 nend

nend

    Prodigy

  • Active Members
  • PipPipPip
  • 188 posts

Posted 07 January 2013 - 08:49 AM

I Like this example very much, but with autoit 3.3.8.1. it wont work anymore, does anybody know how to fix it.
This piece of code is just to difficult for me.

I Know It's a long time ago this example.

Edited by nend, 07 January 2013 - 08:49 AM.


#13 guinness

guinness

    all-consuming swarm in inconspicuous disguise

  • Developers
  • 17,661 posts

Posted 07 January 2013 - 10:29 AM

Why doesn't it work exactly.

Note: I haven't downloaded or tested as I don't feel like doing all the leg work.

Example List: _AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrGeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()LockFile()Mapping CtrlIDsParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...
Updated: 26/09/2014


#14 nend

nend

    Prodigy

  • Active Members
  • PipPipPip
  • 188 posts

Posted 07 January 2013 - 11:09 AM

Hoi Guinness,

It's make a ico but the ico is corupted (not showing the picture).
With a older version of autoit it was working perfectly.

It won't give any error.

I wish I can debug this my self but the code is "way over my head".



Why doesn't it work exactly.

Note: I haven't downloaded or tested as I don't feel like doing all the leg work.



#15 UEZ

UEZ

    Never say never

  • MVPs
  • 5,079 posts

Posted 07 January 2013 - 01:47 PM

The problem is probably the Hex() function which is different now compared to previous versions.

Br,
UEZ

Edited by UEZ, 07 January 2013 - 01:47 PM.

 
The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯


#16 nend

nend

    Prodigy

  • Active Members
  • PipPipPip
  • 188 posts

Posted 07 January 2013 - 01:55 PM

Thanks UEZ,

I will look into this.


The problem is probably the Hex() function which is different now compared to previous versions.

Br,
UEZ



#17 UEZ

UEZ

    Never say never

  • MVPs
  • 5,079 posts

Posted 07 January 2013 - 01:57 PM

Try this:

AutoIt         
;<a href='http://www.autoitscript.com/forum/index.php?showtopic=101305' class='bbc_url' title=''>http://www.autoitscript.com/forum/index.php?showtopic=101305</a> #include <GDIPlus.au3> #include <WinAPI.au3> Opt("MustDeclareVars", 1) Global $sRegPath, $sImagePath, $hImage, $hIcon ; Get the path of the image $sRegPath = "HKLM\SOFTWARE\AutoIt v3\AutoIt" If StringInStr("X64IA64", @OSArch) Then $sRegPath = StringReplace($sRegPath, "SOFTWARE", "SOFTWARE\Wow6432Node") $sImagePath = RegRead($sRegPath, "InstallDir") & "\Examples\GUI\logo4.gif" ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $sImagePath = ' & $sImagePath & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console ; Start GDIPlus _GDIPlus_Startup() ; Load image $hImage = _GDIPlus_ImageLoadFromFile($sImagePath) ; Create a HICON from the image, ; Before doing this you should really scale your image to an icon size! ; But I just wanted to show that it works..lol $hIcon = _GDIPlus_BitmapCreateHICONFromBitmap($hImage) ;Clean up and shutdown GDIPlus _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() If FileExists(@ScriptDir & "\HICON to ICO.ico") Then FileDelete(@ScriptDir & "\HICON to ICO.ico") ; Create an ico file from the image _CreateIconFileFromHICON($hIcon, @ScriptDir & "\HICON to ICO.ico") ; Destroy the HICON now I've finished with it. _WinAPI_DestroyIcon($hIcon) Func _CreateIconFileFromHICON($hIcon, $sOutIcon)     Local $aInfo, $sIco, $sBmp, $hCDC, $tBI, $tBits, $iSz, $sBD, $FO     ; Start of single Icon Header 3 x 2 bytes = 6 bytes: 0000 Reserved / 0100 Icon / 0100 Numer of icons, total length will be 22 bytes for a single icon when finished     $sIco = "0x000001000100"     ; Start of the Bitmap data header 1 x 4bytes: length of the header will be 40 bytes when finished. Will be appended to the end of the icon header when finished     $sBmp = "28000000"     ; Get info about the HICON, this is mainly to get the pointers to the Color/Mask bitmaps data     $aInfo = _WinAPI_GetIconInfo($hIcon)     ; Create a memory Compatable DC     $hCDC = _WinAPI_CreateCompatibleDC(0)     ; Create a BITMAPINFO Struct to store the Bitmap Info, it needs to be inilialized by setting the struct size.     $tBI = DllStructCreate($tagBITMAPINFO)     DllStructSetData($tBI, "Size", DllStructGetSize($tBI))     ; Pass a bitmap data pointer to the BITMAPINFO struct so we can recieve the details of the color bitmap data, we use it to write the headers     _WinAPI_GetDIBits($hCDC, $aInfo[5], 0, 0, 0, DllStructGetPtr($tBI), 0)     ; Now we have some the basic info to add to the Icon & Bitmap header so we'll add that to the headers.     $sIco &= Hex(DllStructGetData($tBI, "Width"), 2) & Hex(DllStructGetData($tBI, "Height"), 2) & "00000100" & _RB(Hex(DllStructGetData($tBI, "BitCount"), 4))     $sBmp &= _RB(Hex(DllStructGetData($tBI, "Width"), 8)) & _RB(Hex(DllStructGetData($tBI, "Height") * 2, 8)) & "0100" & _RB(Hex(DllStructGetData($tBI, "BitCount"), 4)) & "00000000"     ; Get the size of the Bitmap data from the BITMAPINFO Struct, we'll use this in the headers further on.     $iSz = DllStructGetData($tBI, "SizeImage")     ; Create a struct to store the Bitmap data Bits of the first bitmap, reset the BITMAPINFO struct     $tBits = DllStructCreate("byte[" & DllStructGetData($tBI, "SizeImage") & "]")     ; Get the color bitmap dib bits into the $tBits struct.     DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $aInfo[5], 'int', $iSz, 'ptr', DllStructGetPtr($tBits))     ; Get GetBitmapBits returns Bottom to Top dib, so I turn it to Top to Bottom dib ;)     ; ATM I'm only assuming that GetBitmapBits returns a Bottom to Top dib, maybe the bitmap bits you use could be Top Down already?.     For $i = DllStructGetData($tBI, "SizeImage") + 1 To 0 Step -(DllStructGetData($tBI, "SizeImage") / DllStructGetData($tBI, "Height"))         $sBD &= StringTrimLeft(BinaryMid(DllStructGetData($tBits, 1), $i, (DllStructGetData($tBI, "SizeImage") / DllStructGetData($tBI, "Height"))), 2)     Next     ;Clear the BITMAPINFO & $tBits Struct as we'll use the same variables again for the mask bitmap data     $tBits = 0     $tBI = 0     ; Create a BITMAPINFO Struct to store the Bitmap Info again, it needs to be inilialized by setting the struct size.     $tBI = DllStructCreate($tagBITMAPINFO)     DllStructSetData($tBI, "Size", DllStructGetSize($tBI))     ; Pass a bitmap data pointer to the BITMAPINFO struct so we can recieve the details of the bitmask bitmap data     _WinAPI_GetDIBits($hCDC, $aInfo[4], 0, 0, 0, DllStructGetPtr($tBI), 0)     ; We've finished with the Compatable DC, delete it.     _WinAPI_DeleteDC($hCDC)     ; Add the size of the of the color + bitmask bitmap data as we need this for both the Icon & Bitmap header     $iSz += DllStructGetData($tBI, "SizeImage")     ; combine the bitmap data size with the bitmap header, I'm padding the rest of the 40 byte bitmap header with 0's., that's the Bitmap header done     $sBmp &= _RB(Hex($iSz, 8)) & "00000000000000000000000000000000"     ; Now add the size of the Bitmap data + bitmap header size and combine the icon header together with the bitmap header and color bitmap data     $sIco &= _RB(Hex($iSz + 40, 8)) & _RB(Hex("22", 8)) & $sBmp & $sBD     ; Create a struct to store the Bitmap dib Bits of the mask bitmap     $tBits = DllStructCreate("byte[" & DllStructGetData($tBI, "SizeImage") & "]")     ; Get the mask bitmap dib bits into the $tBits struct.     DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $aInfo[4], 'int', DllStructGetData($tBI, "SizeImage"), 'ptr', DllStructGetPtr($tBits))     ; Get GetBitmapBits returns Bottom to Top dib, so I turn it to a Top to Bottom dib and append the mask bitmap data to the icon     For $i = DllStructGetData($tBI, "SizeImage") + 1 To 0 Step -(DllStructGetData($tBI, "SizeImage") / DllStructGetData($tBI, "Height"))         $sIco &= StringTrimLeft(BinaryMid(DllStructGetData($tBits, 1), $i, (DllStructGetData($tBI, "SizeImage") / DllStructGetData($tBI, "Height"))), 2)     Next     ; Write the icon to a file.     $FO = FileOpen($sOutIcon, 18)     FileWrite($sOutIcon, Binary($sIco))     FileClose($FO)     ; Clear the structs     $tBits = 0     $tBI = 0 EndFunc   ;==>_CreateIconFileFromHICON Func _GDIPlus_BitmapCreateHICONFromBitmap($hBitmap)     Local $hIcon     $hIcon = DllCall($ghGDIPDll, "int", "GdipCreateHICONFromBitmap", "hwnd", $hBitmap, "int*", 0)     If @error Then Return SetError(@error, 0, -1)     Return SetError($hIcon[0], 0, $hIcon[2]) EndFunc   ;==>_GDIPlus_BitmapCreateHICONFromBitmap ; Reverse Byte String Func _RB($sByte)     Local $aX = StringRegExp($sByte, "(.{2})", 3), $sX = ''     For $i = UBound($aX) - 1 To 0 Step -1         $sX &= $aX[$i]     Next     Return $sX EndFunc   ;==>_RB


It works for me using 3.3.8.1 and Win7 x64.

Br,
UEZ

 
The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯


#18 ptrex

ptrex

    Universalist

  • MVPs
  • 2,420 posts

Posted 07 January 2013 - 03:46 PM

@UEZ

The file is created 47 Kb large, but can't be opened ?

Win 7 X64 3.3.8.0

#19 nend

nend

    Prodigy

  • Active Members
  • PipPipPip
  • 188 posts

Posted 07 January 2013 - 03:49 PM

Thanks UEZ!!!

Ik works perfectly. :thumbsup:

#20 ptrex

ptrex

    Universalist

  • MVPs
  • 2,420 posts

Posted 07 January 2013 - 04:14 PM

@nend

Which program are you using to open it ? Because using IrFanView doesn't like it !

"Invalid or unsupported ICO file"

rgds
ptrex




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users