Jump to content

HICON to .ico file


smashly
 Share

Recommended Posts

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

#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
Link to comment
Share on other sites

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

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

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"

Link to comment
Share on other sites

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

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

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...

Link to comment
Share on other sites

  • 3 years later...

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
Link to comment
Share on other sites

Why doesn't it work exactly.

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

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_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()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Try this:

;http://www.autoitscript.com/forum/index.php?showtopic=101305
#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

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...