You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否将PNG图片打包进资源DLL并配合ImageSearch函数使用?

解决方案:将PNG打包进DLL供ImageSearch使用,及无额外文件的替代方案

首先直接回应你的核心疑问:ImageSearch原生并不支持直接读取DLL资源中的PNG文件——它只接受本地文件路径作为搜索目标。不过我们可以通过“提取资源到临时存储”的方式间接实现,同时完全避免在脚本目录留下文件痕迹。下面分方案详细说明:

一、DLL资源打包方案(隐藏图片到DLL)

这个方案的思路是把PNG作为自定义资源打包进DLL,脚本运行时临时提取到系统临时目录(用完即删),再传递给ImageSearch。

步骤1:打包PNG到DLL

用资源编辑器(比如Visual Studio自带的资源编辑器,或者免费的Resource Hacker)创建一个空DLL,添加你的PNG文件作为资源:

  • 资源类型设为自定义类型(比如命名为PNG)
  • 给资源分配一个唯一ID(比如101)

步骤2:脚本中提取并调用ImageSearch

以下是AutoHotkey的实现示例(假设你的资源DLL名为resource.dll):

; 从DLL提取PNG资源到临时文件
ExtractPNGFromDLL(dllPath, resourceID, tempFilePath) {
    ; 加载DLL模块
    hModule := DllCall("LoadLibrary", "Str", dllPath, "Ptr")
    if (!hModule) {
        MsgBox, 无法加载资源DLL
        return false
    }
    ; 查找指定资源
    hResource := DllCall("FindResource", "Ptr", hModule, "Ptr", resourceID, "Str", "PNG", "Ptr")
    if (!hResource) {
        DllCall("FreeLibrary", "Ptr", hModule)
        MsgBox, 无法找到目标PNG资源
        return false
    }
    ; 获取资源大小并锁定内存
    resourceSize := DllCall("SizeofResource", "Ptr", hModule, "Ptr", hResource, "UInt")
    pResource := DllCall("LoadResource", "Ptr", hModule, "Ptr", hResource, "Ptr")
    pLocked := DllCall("LockResource", "Ptr", pResource, "Ptr")
    
    ; 写入系统临时文件
    file := FileOpen(tempFilePath, "wb")
    file.RawWrite(pLocked, resourceSize)
    file.Close()
    
    ; 释放DLL
    DllCall("FreeLibrary", "Ptr", hModule)
    return true
}

; 实际调用示例
tempPNG := A_Temp "\temp_search_img.png" ; 用系统临时目录,用户几乎不会注意
if (ExtractPNGFromDLL("resource.dll", 101, tempPNG)) {
    ; 执行ImageSearch
    ImageSearch, foundX, foundY, 0, 0, A_ScreenWidth, A_ScreenHeight, %tempPNG%
    if (ErrorLevel = 0) {
        MsgBox, 目标图片已找到!位置:%foundX%, %foundY%
    }
    ; 用完立即删除临时文件
    FileDelete, %tempPNG%
}

这个方案的优势是图片被隐藏在DLL中,普通用户很难察觉到其中包含图像资源;临时文件在系统临时目录,用完即删,不会留下痕迹。

二、无需额外DLL的替代方案

如果不想额外分发DLL,以下几种方案同样可以实现“不附带PNG文件”的需求:

1. 将PNG编码为Base64嵌入脚本

把PNG转换成Base64字符串,直接嵌入到脚本代码中,运行时解码到临时文件使用。这种方案不需要任何额外文件,脚本本身就是单文件。

示例代码:

; 替换成你的PNG对应的Base64字符串(可以用在线工具转换)
pngBase64 := "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg=="
tempPNG := A_Temp "\temp_img.png"

; 解码Base64到临时文件
FileDelete, %tempPNG%
; 获取解码后的字节大小
DllCall("Crypt32.dll\CryptStringToBinary", "Str", pngBase64, "UInt", 0, "UInt", 1, "Ptr", 0, "UIntP", outSize, "Ptr", 0, "Ptr", 0)
VarSetCapacity(buffer, outSize, 0)
; 执行解码
DllCall("Crypt32.dll\CryptStringToBinary", "Str", pngBase64, "UInt", 0, "UInt", 1, "Ptr", &buffer, "UIntP", outSize, "Ptr", 0, "Ptr", 0)
; 写入文件
File := FileOpen(tempPNG, "wb")
File.RawWrite(&buffer, outSize)
File.Close()

; 调用ImageSearch
ImageSearch, foundX, foundY, 0, 0, A_ScreenWidth, A_ScreenHeight, %tempPNG%
if (ErrorLevel = 0) {
    MsgBox, 找到图片!
}
; 清理临时文件
FileDelete, %tempPNG%

2. 使用支持内存图像的搜索库(无临时文件)

原生ImageSearch依赖文件,但一些第三方AHK库(比如Gdip.ahk)支持直接加载内存中的图像数据进行像素搜索。流程是:

  • 从DLL/Base64获取PNG的字节流
  • 用Gdip将字节流加载为内存中的图像对象
  • 调用Gdip的图像搜索函数进行匹配

这种方案完全不需要生成临时文件,隐蔽性最高,但需要引入第三方库并稍作学习。

3. 编译脚本时嵌入PNG到EXE

如果你使用AutoHotkey的编译工具,可以用FileInstall将PNG嵌入到编译后的EXE中,运行时释放到系统临时目录而不是脚本目录:

; 第三个参数设为1表示覆盖,将PNG安装到系统临时目录
FileInstall, search.png, %A_Temp%\search.png, 1
; 执行搜索
ImageSearch, foundX, foundY, 0, 0, A_ScreenWidth, A_ScreenHeight, %A_Temp%\search.png
; 用完删除
FileDelete, %A_Temp%\search.png

编译后的EXE是单文件,用户看不到PNG,运行时临时释放的文件也会被立即删除。

总结

  • 若追求“图片隐藏在DLL中”,选择DLL资源+临时文件方案;
  • 若想要最轻量化的单文件方案,选择Base64嵌入或编译时嵌入PNG;
  • 若完全不想生成任何临时文件,选择Gdip内存图像搜索方案。

内容的提问来源于stack exchange,提问作者msmilkshake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:56:00