如何在golang中从windows`syscall`加载图像资源?

Posted

技术标签:

【中文标题】如何在golang中从windows`syscall`加载图像资源?【英文标题】:How to load image resource from windows `syscall` in golang? 【发布时间】:2017-03-17 03:51:10 【问题描述】:

我正在编写一个使用go-bindata嵌入图像资源的golang程序,并使用Asset(string) ([]byte, error)函数访问资源。但是我现有的库代码是这样的:

func NewIconFromFile(filePath string) (uintptr, error) 
    absFilePath, err := filepath.Abs(filePath)
    if err != nil 
        return 0, err
    
    hicon, _, _ := LoadImage.Call(
        0,
        uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(absFilePath))),
        IMAGE_ICON,
        0,
        0,
        LR_DEFAULTSIZE|LR_LOADFROMFILE)
    if hicon == 0 
        return 0, errors.New("load image failed: " + filePath)
    
    return hicon, nil

如何将这些函数重写为:

 func NewIconFromRawBytes(imgBytes []byte) (uintptr, error) 

所以它可以支持从[]byte 加载图像?有什么帮助吗?谢谢。

编辑:有a similar c++ version question,如何将其移植到golang。

【问题讨论】:

你为什么要返回uintptr 什么是LoadImage?您的代码中似乎有很多假设没有得到充分解释,无法提供答案。 @apxp:这不是警告的意思,只要你看到“不安全”就盲目地重复是没有用的。在 Go 中,很多东西都需要 unsafepackage,例如使用sys/syscall 软件包,并且在未来版本中完全支持正确使用。该警告意味着可以以依赖内部实现或平台特定细节的方式使用 unsafe,而不是简单地导入它会使您的程序不合规。 @Flimzy 原始代码可以在github repo找到:xilp/systray。 @Flimzy 此代码严格处理 Windows API;如果您知道在 Go 中使用它是什么,则没有任何假设。 【参考方案1】:

LoadImage() 处理直接内置在 Windows 可执行文件中的 Windows 资源。 go-bindata 好像没有处理这些,直接用 Go 做这些也不是小事。

如果您希望能够编写一个 NewIconFromRawBytes() 来从内存中创建一个 HICON,您将需要使用名称容易混淆的 CreateIconFromResourceEx() 函数。如果您这样做,您可能需要牢记the info in the answer here。

但是,如果这是一个图像而不是一个图标,并且您希望从中得到一个 HBITMAP,那么您还有更多的工作要做,涉及到 CreateDIBSection() 函数。 The answer here shows what to do, though understanding it may be a bit harder. 需要注意的是,CreateDIBSection() 会为您分配图像内存,因此您必须将其从 Go 复制到提供的内存位置。

旁注:如果您有*image.RGBA*image.NRGBA,如果要将其推入HBITMAP,则需要翻转字节,因为Windows 需要BGRA 中的字节顺序,不是RGBA 订单。

【讨论】:

以上是关于如何在golang中从windows`syscall`加载图像资源?的主要内容,如果未能解决你的问题,请参考以下文章

golang---获取windows系统相关信息

golang 观察Golang Syscall和Runtime函数活动

golang调度学习-调度流程 Syscall

golang调用DLL中的函数

将字节数组转换为 Golang 中的 syscall.InotifyEvent 结构

Golang在windows与linux的部分区别