Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate

FileExtract / FileExtract_ToMem Examples for Unicode Builds


  • Please log in to reply
34 replies to this topic
  • Guests
  • Last active:
  • Joined: --
Uh-huh, that sounds like it. Thanks for your insight.

  • Guests
  • Last active:
  • Joined: --
When using memcpy, should the old buffer be manually discarded or does it automatically gets cleared?

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
memcpy just copies the data, nothing more. You can't clear read-only memory.

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.



  • Guests
  • Last active:
  • Joined: --
Hmm, thanks for the info. That means once resource files are loaded with the LoadScriptResource function they remain in the memory until the script exits. I was planning to install all icons and background images for guis as resource. If the total size of them is, let's say, 10mb and they are all loaded with the function, does it mean the script uses at least 10mb of memory?

  • Guests
  • Last active:
  • Joined: --
Hi Lexikos,

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?

  • Guests
  • Last active:
  • Joined: --
Now I'm trying to show a resource image of a compiled script and this doesn't work. It shows the image in non-compiled script though. Does anybody know why?

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, ~


HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
:?:
hBitmap := LoadBitmapFromBuffer([color=red]pData[/color], 640, 480)


  • Guests
  • Last active:
  • Joined: --

:?:

hBitmap := LoadBitmapFromBuffer([color=red]pData[/color], 640, 480)

It doesn't seem to work. I get a black image. Does it work for you?

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
I have changed a few things and also included improved LoadScriptResource(), Lexikos can you please update yours too if you agree?

@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, ~


Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

Lexikos can you please update yours too if you agree?

What reasons do you have for the seemingly unnecessary copying and "freeing" in LoadScriptResource?

[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



HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
thanks for the note, I adapted above 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.

  • Guests
  • Last active:
  • Joined: --

@Guest, try this:

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?

  • Guests
  • Last active:
  • Joined: --
Can we use the LoadImage function for resource images installed with FileInstall? I'm not sure what to put the resource name for the second parameter, lpszName.

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
You can use Resource Hacker or any other resource editor to view the resource names. They should be the same as FileInstall's first parameter, but in upper-case.

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.

  • Guests
  • Last active:
  • Joined: --
I see. Thanks, Lexikos, for the input.