2

I am writing a golang program using go-bindata to embed the image resources, and use the Asset(string) ([]byte, error) function to access resources. But my existing library codes go like this:

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
}

How can I rewrite this functions to:

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

so it can support for loading images from []byte ? Any helps? thanks.

Edit: There is a similar c++ version question, how can I port it to golang.

Community
  • 1
  • 1
qtopierw
  • 1,447
  • 14
  • 23
  • Why are you returning a `uintptr`? – Jonathan Hall Mar 17 '17 at 10:19
  • What is `LoadImage`? There seem to be a lot of assumptions in your code that aren't explained sufficiently to provide an answer. – Jonathan Hall Mar 17 '17 at 10:20
  • @apxp: that's not what the warning means, and it's not useful to blindly repeat anytime you see "unsafe". The `unsafe`package is required for many things in Go, e.g. using the `sys`/`syscall` packages, and when used correctly is fully supported in future versions. That warning means it's possible to use unsafe in a way that relies on internal implementation or platform specific details, not that simply importing it makes your program non-compliant. – JimB Mar 17 '17 at 13:22
  • @Flimzy The original codes can be found at github repo: [xilp/systray](https://github.com/xilp/systray/blob/master/tray_windows.go). – qtopierw Mar 17 '17 at 15:19
  • @Flimzy This code strictly deals with Windows API; there are no assumptions if you know what working with it in Go is about. – andlabs May 28 '17 at 20:00

1 Answers1

1

LoadImage() deals with Windows resources, which are built into Windows executables directly. go-bindata doesn't seem to deal in these, and doing this with Go directly isn't trivial.

If you want to be able to write a NewIconFromRawBytes() that creates an HICON from memory, you'll need to use the confusingly-named CreateIconFromResourceEx() function. If you do that, you may want to keep the info in the answer here in mind.

If, however, this is an image instead of an icon and you want an HBITMAP out of it, you have a bit more work to do involving the CreateDIBSection() function. The answer here shows what to do, though understanding it may be a bit harder. Of important note is that CreateDIBSection() allocates the image memory for you, so you'll have to copy it from Go to the memory location provided.

Side note: if you have a *image.RGBA or *image.NRGBA, you'll need to flip the bytes around if you want to shove that into an HBITMAP, as Windows expects the bytes in BGRA order, not RGBA order.

andlabs
  • 11,290
  • 1
  • 31
  • 52