使用本地Golang API在Windows上添加图标托盘

I'm developing a daemon with no UI apart from a simple icon in the Windows systray.

I would like to have no dependencies on any other package(s), so I'm trying to use the syscall package and implement the necessary call(s) by myself.

Documentation

Libraries

Implementation

Structures

Built with xilp/systray documentation.

type HANDLE uintptr

type HICON HANDLE
    type HWND HANDLE

type GUID struct {
    Data1 uint32
    Data2 uint16
    Data3 uint16
    Data4 [8]byte
}

type NOTIFYICONDATA struct {
    CbSize           uint32
    HWnd             HWND
    UID              uint32
    UFlags           uint32
    UCallbackMessage uint32
    HIcon            HICON
    SzTip            [128]uint16
    DwState          uint32
    DwStateMask      uint32
    SzInfo           [256]uint16
    UVersion         uint32
    SzInfoTitle      [64]uint16
    DwInfoFlags      uint32
    GuidItem         GUID
}

Variables

const (
    NIM_ADD = 0x00000000
    NIM_MODIFY = 0x00000001
    NIM_DELETE = 0x00000002
    NIM_SETVERSION = 0x00000004

    NIF_MESSAGE = 0x00000001
    NIF_ICON = 0x00000002
    NIF_TIP = 0x00000004
    NIF_STATE = 0x00000008

    NIF_HIDDEN = 0x00000001
)

Source

package main

import (
    "log"
    "syscall"
    "unsafe"
)

func main() {
    shell32 := syscall.MustLoadDLL("shell32.dll")
    Shell_NotifyIcon := shell32.MustFindProc("Shell_NotifyIconW")

    iconData := NOTIFYICONDATA{
        HWnd: 0,
        UFlags: NIF_MESSAGE | NIF_STATE,
        DwState: NIF_HIDDEN,
        DwStateMask: NIS_HIDDEN,
    }
    iconData.CbSize = uint32(unsafe.Sizeof(iconData))

    ret, _, _ := Shell_NotifyIcon.Call(
        NIM_ADD,
        uintptr(unsafe.Pointer(&iconData)),
    )

    if ret == 0 {
        log.Println("Failed")
        return
    }

    // Do anything, like open a HTTP server to keep the program running
    http.ListenAndServe(":8080", nil)
}

Details

  • I have no idea what information to give in HWnd, but without it, the executable crashes.
  • UFlags, DwState and DwStateMask have values that I have found in different projects.

I know that it is possible; the Golang WIKI gives an implementation to call a message box.