Apologies,
nnnik, but you misunderstood: I didn't suggest adding such AHK functions - was merely stating that in the absence of direct assignment between binary variables, user has to perform all those API calls through DllCall(), which induces a high overhead.
As for those APIs themselves yes, they may be deprecated, but I recently read a topic in the old forum where somebody - Lexikos himself, if I'm not mistaken - performed a speed comparison between GlobalAlloc() and a few similar others, and that one still came up first, despite the statement at MSDN that it would be slower. But that's of no concern for the user - if that operation would be implemented internally I'm sure Lexikos would choose the best available method.
Here's an example code I was working on, extracted from skwire's sWeather and slightly modified by me. It converts a Base64 string into an icon or bitmap and returns the corresponding handle. You'll notice the API uses the variable called
Dec to store the result, and I want to transfer its binary contents to another variable, to work with subsequently. But I can't, because a simple
Buf := Dec won't copy the entire binary data from Dec to Buf, therefore all the subsequent operations would fail. All those additional DllCalls to GlobalAlloc, GlobalLock etc are required only to perform a simple binary data copy from one place to another.
So what the OP requests and I support that request, is the simple ability to perform assignment of binary data from one variable to another (i.e.
b := a). And maybe binary comparison as well (
if a = b or
if a != b).
Code: Select all
CreateIcon(n, h := False, bmp := False)
{
Static
If h
h%n% := 0
If h%n%
Return h%n%
VarSetCapacity(B64, StrLen(%n%) << !!A_IsUnicode)
B64 := %n%
If !DllCall("Crypt32.dll\CryptStringToBinary"
, "Ptr", &B64
, "UInt", 0
, "UInt", 0x1
, "Ptr", 0
, "UIntP", DecLen
, "Ptr", 0
, "Ptr", 0)
Return False
VarSetCapacity(Dec, DecLen, 0)
If !DllCall("Crypt32.dll\CryptStringToBinary"
, "Ptr", &B64
, "UInt", 0
, "UInt", 0x1
, "Ptr", &Dec
, "UIntP", DecLen
, "Ptr", 0
, "Ptr", 0)
Return False
if (AHKBinaryAssignment=True) ; which is not, unfortunately
{
Buf := Dec
DllCall("Ole32.dll\CreateStreamOnHGlobal", "Ptr", &Buf, "Int", True, "PtrP", pStream)
}
else
{
hData := DllCall("Kernel32.dll\GlobalAlloc", "UInt", 2, "UPtr", DecLen, "UPtr")
pData := DllCall("Kernel32.dll\GlobalLock", "Ptr", hData, "UPtr")
DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", pData, "Ptr", &Dec, "UPtr", DecLen)
DllCall("Kernel32.dll\GlobalUnlock", "Ptr", hData)
DllCall("Ole32.dll\CreateStreamOnHGlobal", "Ptr", hData, "Int", True, "PtrP", pStream)
}
DllCall("Gdiplus.dll\GdipCreateBitmapFromStream", "Ptr", pStream, "PtrP", pBitmap)
t := bmp ? "HBITMAP" : "HICON"
DllCall("Gdiplus.dll\GdipCreate" t "FromBitmap", "Ptr", pBitmap, "PtrP", h%n%, "UInt", 0)
DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", pBitmap)
DllCall(NumGet(NumGet(pStream + 0, 0, "UPtr") + (A_PtrSize * 2), 0, "UPtr"), "Ptr", pStream)
;DllCall("Kernel32\GlobalFree", "Ptr", hData) ; probably not needed, if second parameter is True in CreateStreamOnHGlobal()
Return h%n%
}