FileExtract / FileExtract_ToMem Examples for Unicode Builds
The pointer returned by LockResource is valid until the module containing the resource is unloaded. It is not necessary to unlock resources because the system automatically deletes them when the process that created them terminates.
...
Note LockResource does not actually lock memory; it is just used to obtain a pointer to the memory containing the resource data.
I did a simple test and indeed the memory doesn't get released until the script exits. The following script uses 17mb of memory when it's compiled. The used file for testing is video.wmv and the size is 13mb.
if A_IsCompiled { ;the wmv file is about 13mb and the script momory usage becomes 17mb data := LoadScriptResource(".\video.wmv", size) } Return LoadScriptResource(Name, ByRef DataSize = 0, Type = 10) { lib := DllCall("GetModuleHandle", "ptr", 0, "ptr") res := DllCall("FindResource", "ptr", lib, "str", Name, "ptr", Type, "ptr") DataSize := DllCall("SizeofResource", "ptr", lib, "ptr", res, "uint") hresdata := DllCall("LoadResource", "ptr", lib, "ptr", res, "ptr") return DllCall("LockResource", "ptr", hresdata, "ptr") } FileInstall, .\video.wmv, ~Is there a way to release memory of loaded resources without quiting the script?
This script requires a bmp file named Tulips.bmp in the script directory.
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. if A_IsCompiled { pData := LoadScriptResource(".\Tulips.bmp", size) ; VarSetCapacity(Data, size) ; DllCall("msvcrt\memcpy", "str", Data, "ptr", pData, "ptr", size) hBitmap := LoadBitmapFromBuffer(*pData, 640, 480) } else { FileRead, Bitmap, *c %A_ScriptDir%\Tulips.bmp hBitmap := LoadBitmapFromBuffer(Bitmap, 640, 480) } Gui, Margin, 20, 20 Gui, Add, Picture, w640 h480 0xE hWndPic1 SendMessage, 0x172, 0x0, hBitmap, , ahk_id %Pic1% Gui, Show Return GuiClose: Gui, Destroy Bitmap := hBitmap := "" Return LoadScriptResource(Name, ByRef DataSize = 0, Type = 10) { lib := DllCall("GetModuleHandle", "ptr", 0, "ptr") res := DllCall("FindResource", "ptr", lib, "str", Name, "ptr", Type, "ptr") DataSize := DllCall("SizeofResource", "ptr", lib, "ptr", res, "uint") hresdata := DllCall("LoadResource", "ptr", lib, "ptr", res, "ptr") return DllCall("LockResource", "ptr", hresdata, "ptr") } LoadBitmapFromBuffer(BitmapBuffer, width, height) { ;modified the SKAN's code http://www.autohotkey.com/forum/post-182041.html#182041 hBitmap := DllCall( "CreateDIBitmap" , Ptr, DllCall("GetDC", Ptr, A_ScriptHwnd, Ptr) , Ptr, bmiHAddr:=&BitmapBuffer+14 , UInt, (CBM_INIT:=4) , Ptr, &BitmapBuffer+NumGet(BitmapBuffer,10, "Int") , Ptr, &BitmapBuffer+14 , UInt, DIB_PAL_COLORS:=1 , Ptr) Return DllCall("CopyImage" , Ptr, hBitmap , UInt, 0 , Int, width , Int, height , UInt, 0x00000008 ;LR_COPYDELETEORG , Ptr) } FileInstall, .\Tulips.bmp, ~
hBitmap := LoadBitmapFromBuffer([color=red]pData[/color], 640, 480)
It doesn't seem to work. I get a black image. Does it work for you?:?:
hBitmap := LoadBitmapFromBuffer([color=red]pData[/color], 640, 480)
@Guest, try this:
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. if A_IsCompiled { If [color=red]size := LoadScriptResource(pData,[/color]".\Tulips.bmp") hBitmap := LoadBitmapFromBuffer(pData, 640, 480) else MsgBox Resource could not be loaded! } else { FileRead, Bitmap, *c %A_ScriptDir%\Tulips.bmp hBitmap := LoadBitmapFromBuffer(Bitmap, 640, 480) } Gui, Margin, 20, 20 Gui, Add, Picture, w640 h480 0xE hWndPic1 SendMessage, 0x172, 0x0, hBitmap, , ahk_id %Pic1% Gui, Show Return GuiClose: Gui, Destroy Bitmap := hBitmap := "" [color=red]ExitApp [/color] Return LoadScriptResource(ByRef Data,Name, Type = 10) { lib := DllCall("GetModuleHandle", "ptr", 0, "ptr") res := DllCall("FindResource", "ptr", lib, "str", Name, "ptr", Type, "ptr") DataSize := DllCall("SizeofResource", "ptr", lib, "ptr", res, "uint") hresdata := DllCall("LoadResource", "ptr", lib, "ptr", res, "ptr") [color=red]VarSetCapacity(Data,DataSize) DllCall("RtlMoveMemory","PTR",&Data,"PTR",DllCall("LockResource", "ptr", hresdata, "ptr"),"UInt",DataSize)[/color] return DataSize } LoadBitmapFromBuffer([color=red]ByRef BitmapBuffer[/color], width, height) { ;modified the SKAN's code http://www.autohotkey.com/forum/post-182041.html#182041 hBitmap := DllCall( "CreateDIBitmap" , Ptr, DllCall("GetDC", Ptr, A_ScriptHwnd, Ptr) , Ptr, bmiHAddr:=&BitmapBuffer+14 , UInt, (CBM_INIT:=4) , Ptr, &BitmapBuffer+NumGet(BitmapBuffer,10, "Int") , Ptr, &BitmapBuffer+14 , UInt, DIB_PAL_COLORS:=1 , Ptr) Return DllCall("CopyImage" , Ptr, hBitmap , UInt, 0 , Int, width , Int, height , UInt, 0x00000008 ;LR_COPYDELETEORG , Ptr) } FileInstall, .\Tulips.bmp, ~
What reasons do you have for the seemingly unnecessary copying and "freeing" in LoadScriptResource?Lexikos can you please update yours too if you agree?
[This function is obsolete and is only supported for backward compatibility with 16-bit Windows. For 32-bit Windows applications, it is not necessary to free the resources loaded using LoadResource. If used on 32 or 64-bit Windows systems, this function will return FALSE.]
Source: FreeResource function
But I still think it is better to store the data in variable, otherwise we should call it ResourcePointer() or similar.
Also if it is a pure text you can use SubStr, Loop,Parse and so on straight away and pass your variable to ByRef functions directly.
Great, it works thanks. I wonder why Byref is necessary for LoadBitmapFromBuffer() and copying the loaded resource in LoadScriptResource(). Does that mean a read-only resource image cannot be displayed?@Guest, try this:
LoadImage probably expects an RT_IMAGE, RT_ICON or similar resource. FileInstall creates a RT_RCDATA resource, so it probably won't work. However, WebBrowser (Shell.Explorer ActiveX) controls can use any type of resource as the source for an image via the res:// protocol.