Ajouter une barre d’icons sous Windows en utilisant l’API Golang native

Je développe un démon sans interface utilisateur autre qu’une simple icône dans la barre des tâches Windows.

Je voudrais ne pas avoir de dépendances sur les autres paquets, alors j’essaie d’utiliser le paquetage syscall et d’implémenter moi-même les appels nécessaires.

Documentation

  • Après quelques recherches, je pense que je dois utiliser la fonction Shell_NotifyIcon dans shell32.dll .
  • Le WIKI de Golang propose trois méthodes pour appeler une DLL Windows . La troisième solution doit être exclue. Pour plusieurs raisons, je veux construire des sources avec le compilateur Golang uniquement.
  • J’ai trouvé un article intéressant sur “Le développement de plates-formes multiples avec Go” qui expliquait comment utiliser Shell_NotifyIconW (déclinaison Unicode), mais l’implémentation est partielle.
  • J’ai trouvé quelques bibliothèques de Golang qui implémentent la barre d’état système Windows. Ils sont utiles pour aider à comprendre la structure et les appels à intervenir.

Bibliothèques

  • getlantern / systray
  • cratonica / trayhost
  • xilp / systray
  • lxn / marcher

la mise en oeuvre

Les structures

Construit avec la documentation xilp / systray .

 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 } 

Les 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 ) 

La 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) } 

Détails

  • Je n’ai aucune idée de l’information à donner dans HWnd , mais sans elle, l’exécutable se bloque.
  • UFlags , DwState et DwStateMask ont des valeurs que j’ai trouvées dans différents projets.

Je sais que c’est possible; le Golang WIKI donne une implémentation pour appeler une boîte de message.