Convert Base64PNG_to_HICON to v2 Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
User avatar
Umbracinis
Posts: 5
Joined: 02 Jun 2023, 10:08

Convert Base64PNG_to_HICON to v2

Post by Umbracinis » 02 Jun 2023, 12:11

Context: Windows 11 Pro x64 (Eng) v22H2,
OS build: 22621.1702,
AutoHotkey x64 v2.0.2.0

First time posting here, so apologies if I am doing something wrong.

I am now trying to implement an icon encoded with base64 in my script instead
of referencing an external (ico) file. Yes, I know that I can compile and specify
an icon, but I prefer the icon in the source script.

I searched and came across a function called Base64PNG_to_HICON,
by a chap called SKAN, found here:
This seems to be what I need, however it is for v1. I am trying to
convert it to v2, but have encountered an error that I cannot overcome:

Error: Parameter #1 of VarSetStrCapacity
requires a variable reference, but received an Integer.

Specifically: 0
036: Return DllCall("Crypt32.dll\CryptStringToBinary", "Str",Base64PNG,
"UInt",BLen, "UInt",1 ,"Ptr",&(Bin := VarSetStrCapacity(Bin, nBytes)),
"UIntP",nBytes, "UInt",0, "UInt",0) ? DllCall("CreateIconFromResourceEx",
"Ptr",&Bin, "UInt",nBytes, "Int",True, "UInt" ,0x30000, "Int",W, "Int",H,
"UInt",0, "UPtr") : 0

Here is my version of SKAN's function:

Code: Select all

Base64PNG_to_HICON(Base64PNG, W:=0, H:=0)
{
  Local BLen   := StrLen(Base64PNG), Bin:=0
  Local nBytes := Floor(StrLen(RTrim(Base64PNG,"="))*3/4)
  Return DllCall("Crypt32.dll\CryptStringToBinary", "Str",Base64PNG, "UInt",BLen, "UInt",1
            ,"Ptr",&(Bin := VarSetStrCapacity(Bin, nBytes)), "UIntP",nBytes, "UInt",0, "UInt",0)
       ? DllCall("CreateIconFromResourceEx", "Ptr",&Bin, "UInt",nBytes, "Int",True, "UInt"
            ,0x30000, "Int",W, "Int",H, "UInt",0, "UPtr")
       : 0            
}

I have searched for solutions from the forum, the web, and a few deities,
all to no avail.
Could someone with more experience point me in the right direction?
Any help would be very acceptable.

Here is my complete test script, ready to run:

Code: Select all

;-----------------------------------------------------------------------------
; Auto-execute section
;-----------------------------------------------------------------------------
#Requires AutoHotkey v2.0
#SingleInstance Force
#Warn


;-----------------------------------------------------------------------------
; Configuration and variables 
;-----------------------------------------------------------------------------
Base64PNG := " ; Small 16px x 16px green leaf
  (
    iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABpElEQVR42p2TQShEURiFb6ZmMS
    sLWSilzEwUReyUBZmVjY2SKGWBBVKahSxISFHYGbFAEouRlDTKYiJFo4wFVsLC0kKN1fV/d+bq
    zsukvDq9+95/zvnPf+97Sv1xtUyqSHNUrQpuBBp0LZXrzmW/jkyrTCFRQLArBD24UaHXkr36ID
    Wqk29Rs75+X9HD29U6HFHdv4mnEC6ctOnEc1YUf+gwArD31KQnEj6SvAg94BXf0hERXXpiRYZs
    DdfTYT17lX0nY6QLiiHSvX9LGTHxrRhgJgnuXPEMm3L/OWdEkIhNAmJz5z0Y2ZcE8aAWjf4xEL
    cMAuabT1QZEsCUUcDR44DeTLWaOnevgREvJksNMXdEZk10ZrYYP1aGl2fAg52PPUDMcWHgFVt4
    E1wwn7vjgCTMb+e2o4E8g8Y+NWTJ7DgnYOHOTgO7N9L01B1hBzEjIPLGdTvDo3tJSNUasUQ+tE
    dHEXeICK0Rz3CoIZZPuF2kPtv9jGLO+VWKYxLvEqIHX/I+JpIGgd/9CINSOBfCh6xrBMWCUI7o
    ol5QVuivrRTUqX9c354hhkwsQvG0AAAAAElFTkSuQmCC
  )"


;-----------------------------------------------------------------------------
; Functions
;-----------------------------------------------------------------------------
; Based on 'Base64PNG_to_HICON' by SKAN:
; https://www.autohotkey.com/boards/viewtopic.php?p=168658#p168658

Base64PNG_to_HICON(Base64PNG, W:=0, H:=0)
{
  Local BLen   := StrLen(Base64PNG), Bin:=0
  Local nBytes := Floor(StrLen(RTrim(Base64PNG,"="))*3/4)
  Return DllCall("Crypt32.dll\CryptStringToBinary", "Str",Base64PNG, "UInt",BLen, "UInt",1
            ,"Ptr",&(Bin := VarSetStrCapacity(Bin, nBytes)), "UIntP",nBytes, "UInt",0, "UInt",0)
       ? DllCall("CreateIconFromResourceEx", "Ptr",&Bin, "UInt",nBytes, "Int",True, "UInt"
            ,0x30000, "Int",W, "Int",H, "UInt",0, "UPtr")
       : 0            
}


;-----------------------------------------------------------------------------
; Execution
;-----------------------------------------------------------------------------
TraySetIcon("HICON:" Base64PNG_to_HICON(Base64PNG))


teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Convert Base64PNG_to_HICON to v2  Topic is solved

Post by teadrinker » 02 Jun 2023, 15:26

Code: Select all

Persistent
Base64PNG := ' ; Small 16px x 16px green leaf
(
    iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABpElEQVR42p2TQShEURiFb6ZmMS
    sLWSilzEwUReyUBZmVjY2SKGWBBVKahSxISFHYGbFAEouRlDTKYiJFo4wFVsLC0kKN1fV/d+bq
    zsukvDq9+95/zvnPf+97Sv1xtUyqSHNUrQpuBBp0LZXrzmW/jkyrTCFRQLArBD24UaHXkr36ID
    Wqk29Rs75+X9HD29U6HFHdv4mnEC6ctOnEc1YUf+gwArD31KQnEj6SvAg94BXf0hERXXpiRYZs
    DdfTYT17lX0nY6QLiiHSvX9LGTHxrRhgJgnuXPEMm3L/OWdEkIhNAmJz5z0Y2ZcE8aAWjf4xEL
    cMAuabT1QZEsCUUcDR44DeTLWaOnevgREvJksNMXdEZk10ZrYYP1aGl2fAg52PPUDMcWHgFVt4
    E1wwn7vjgCTMb+e2o4E8g8Y+NWTJ7DgnYOHOTgO7N9L01B1hBzEjIPLGdTvDo3tJSNUasUQ+tE
    dHEXeICK0Rz3CoIZZPuF2kPtv9jGLO+VWKYxLvEqIHX/I+JpIGgd/9CINSOBfCh6xrBMWCUI7o
    ol5QVuivrRTUqX9c354hhkwsQvG0AAAAAElFTkSuQmCC
)'

TraySetIcon('HICON: ' . Base64PNG_to_HICON(Base64PNG))

Base64PNG_to_HICON(Base64PNG, height := 16) {
    size := StrLen( RTrim(Base64PNG, '=') )*3//4
    if DllCall('Crypt32\CryptStringToBinary', 'Str', Base64PNG, 'UInt', StrLen(Base64PNG), 'UInt', 1,
                                              'Ptr', buf := Buffer(size), 'UIntP', &size, 'Ptr', 0, 'Ptr', 0)
        return DllCall('CreateIconFromResourceEx', 'Ptr', buf, 'UInt', size, 'UInt', true,
                                                   'UInt', 0x30000, 'Int', height, 'Int', height, 'UInt', 0)
    return 0
}

User avatar
Umbracinis
Posts: 5
Joined: 02 Jun 2023, 10:08

Re: Convert Base64PNG_to_HICON to v2

Post by Umbracinis » 03 Jun 2023, 02:38

Wow, it works perfectly! Thank you teadrinker!

I added back the 'width' option, and then thouroghly tested it, and it seems to be working fine.
I am posting it here, in case anyone wants to use it for images that are not exact squares:

Code: Select all

Base64PNG_to_HICON(Base64PNG, width := "0", height := "0") {
    size := StrLen( RTrim(Base64PNG, '=') )*3//4
    if DllCall('Crypt32\CryptStringToBinary', 'Str', Base64PNG, 'UInt', StrLen(Base64PNG),
                                              'UInt', 1, 'Ptr', buf := Buffer(size),
                                              'UIntP', &size, 'Ptr', 0, 'Ptr', 0)
        return DllCall('CreateIconFromResourceEx', 'Ptr', buf, 'UInt', size, 'UInt', true,
                                                   'UInt', 0x30000, 'Int', width,
                                                   'Int', height, 'UInt', 0)
        return 0
}

One again, thank you for your time teadrinker!

teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Convert Base64PNG_to_HICON to v2

Post by teadrinker » 03 Jun 2023, 12:16

It's ok, but there are a few remarks. width and height are numbers, so quotes should not be used. It works with quotes too, but it's technically wrong. Also, I doubt the second parameter is needed, since the icon is always square. :) The last 'return' statement should have a single indentation, not double, it doesn't matter to the interpreter, but it matters for code perception by a human.

User avatar
Umbracinis
Posts: 5
Joined: 02 Jun 2023, 10:08

Re: Convert Base64PNG_to_HICON to v2

Post by Umbracinis » 04 Jun 2023, 04:39

Thank you for your feedback.
teadrinker wrote:
03 Jun 2023, 12:16
It's ok, but there are a few remarks. (...)
Although not a programmer, I have written many short scripts (batch and bash mostly)
for over 20 years as a Systems and Network Administrator, and I was always
a stickler for writing good consistent code, so I really do appreciate your comments.
Even limiting myself to writing within an approximate 80-column limit to improve
readability (like I am doing here, probably to your ire), is something that has
followed me through the decades.

I would like to rewrite my previous entry and correct the code as per your suggestions,
for others that may need it, and after reading other posts it seems to be
possible to do it, however I cannot find a button for doing so. Could you tell how?

Also I like to always use braces with control flow statements (such as 'if'),
and I would like to rewrite the code with that in mind, however I confess that
I find it difficult to interpret the code discussed on this post. Would you
say that the following is correct?

Code: Select all

Base64PNG_to_HICON(Base64PNG, width := 0, height := 0)
{
    size := StrLen( RTrim(Base64PNG, '=') )*3//4
    if DllCall('Crypt32\CryptStringToBinary', 'Str', Base64PNG, 'UInt', StrLen(Base64PNG),
                                              'UInt', 1, 'Ptr', buf := Buffer(size),
                                              'UIntP', &size, 'Ptr', 0, 'Ptr', 0)
    {
        return DllCall('CreateIconFromResourceEx', 'Ptr', buf, 'UInt', size, 'UInt', true,
                                                   'UInt', 0x30000, 'Int', width,
                                                   'Int', height, 'UInt', 0)
    }
    else
    {
      return 0
    }
}

Again, thank you for your time.

gregster
Posts: 8916
Joined: 30 Sep 2013, 06:48

Re: Convert Base64PNG_to_HICON to v2

Post by gregster » 04 Jun 2023, 04:58

Umbracinis wrote:
04 Jun 2023, 04:39
I would like to rewrite my previous entry and correct the code as per your suggestions,
for others that may need it, and after reading other posts it seems to be
possible to do it, however I cannot find a button for doing so. Could you tell how?
As a new user, your posting rights are still limited. This means, you can't currently edit your posts.
However, if you would edit the code in your previous post accordingly, teadrinker's following comment wouldn't fit anymore. This means, readers can't easy follow the original discussion - and it would be more difficult to learn from it. So, that's why such major edits should be avoided - although there are certainly exceptions to this rule.

User avatar
Umbracinis
Posts: 5
Joined: 02 Jun 2023, 10:08

Re: Convert Base64PNG_to_HICON to v2

Post by Umbracinis » 04 Jun 2023, 05:54

Understood gregster, thank you.
If I decide to post an updated version of the code, I shall do it in a new reply.

teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Convert Base64PNG_to_HICON to v2

Post by teadrinker » 04 Jun 2023, 08:02

Umbracinis wrote: Also I like to always use braces with control flow statements (such as 'if'),
and I would like to rewrite the code with that in mind, however I confess that
I find it difficult to interpret the code discussed on this post. Would you
say that the following is correct?
Bracketing an if block is good and correct. However, if the if block ends with return, the subsequent use of else makes no sense, is redundant, and rather makes the code hard to understand.
So, instead of

Code: Select all

if (a) {
    return b
} else {
    do something else...
}
better

Code: Select all

if (a) {
    return b
}
do something else...

User avatar
Umbracinis
Posts: 5
Joined: 02 Jun 2023, 10:08

Re: Convert Base64PNG_to_HICON to v2

Post by Umbracinis » 04 Jun 2023, 10:38

Ah... now I see it: that last return is not part of the if block.
Agreed, that was a rather stupid thing I did.

So it would be like this:

Code: Select all

Base64PNG_to_HICON(Base64PNG, width := 0, height := 0)
{
  size := StrLen( RTrim(Base64PNG, '=') )*3//4
  if DllCall('Crypt32\CryptStringToBinary', 'Str', Base64PNG, 'UInt', StrLen(Base64PNG),
                                            'UInt', 1, 'Ptr', buf := Buffer(size),
                                            'UIntP', &size, 'Ptr', 0, 'Ptr', 0)
  {
    return DllCall('CreateIconFromResourceEx', 'Ptr', buf, 'UInt', size, 'UInt', true,
                                               'UInt', 0x30000, 'Int', width,
                                               'Int', height, 'UInt', 0)
  }
  return 0
}

Thank you teadrinker for your time, big help.

lone525
Posts: 2
Joined: 18 Feb 2023, 22:43

Re: Convert Base64PNG_to_HICON to v2

Post by lone525 » 15 Oct 2023, 17:05

Nice i was looking for this. thank you!

Post Reply

Return to “Ask for Help (v2)”