getlantern / systray

a cross platfrom Go library to place an icon and menu in the notification area
Apache License 2.0
3.28k stars 451 forks source link

The menu disappears when you click #269

Open aleass opened 5 months ago

aleass commented 5 months ago

Hello,when I run and tray, after a while, left or right click will not respond, I do not know whether it is a period of time or some event caused the trigger,but it's running in background,thanks.

aleass commented 5 months ago

system version:

  1. Windows 10

go env:

  1. set GO111MODULE=on
  2. set GOARCH=amd64
  3. set GOBIN=D:\code\bin
  4. set GOCACHE=C:\Users\Administrator\AppData\Local\go-build
  5. set GOENV=C:\Users\Administrator\AppData\Roaming\go\env
  6. set GOEXE=.exe
  7. set GOEXPERIMENT=
  8. set GOFLAGS=
  9. set GOHOSTARCH=amd64
  10. set GOHOSTOS=windows
  11. set GOINSECURE=
  12. set GOMODCACHE=D:\code\pkg\mod
  13. set GONOPROXY=
  14. set GONOSUMDB=
  15. set GOOS=windows
  16. set GOPATH=D:\code
  17. set GOPRIVATE=
  18. set GOPROXY=https://goproxy.io,direct
  19. set GOROOT=D:\code\go_sdk\go1.22.1
  20. set GOSUMDB=sum.golang.org
  21. set GOTMPDIR=
  22. set GOTOOLCHAIN=auto
  23. set GOTOOLDIR=D:\code\go_sdk\go1.22.1\pkg\tool\windows_amd64
  24. set GOVCS=
  25. set GOVERSION=go1.22.1
  26. set GCCGO=gccgo
  27. set GOAMD64=v1
  28. set AR=ar
  29. set CC=gcc
  30. set CXX=g++
  31. set CGO_ENABLED=1
  32. set GOMOD=NUL
  33. set GOWORK=
  34. set CGO_CFLAGS=-O2 -g
  35. set CGO_CPPFLAGS=
  36. set CGO_CXXFLAGS=-O2 -g
  37. set CGO_FFLAGS=-O2 -g
  38. set CGO_LDFLAGS=-O2 -g
  39. set PKG_CONFIG=pkg-config
  40. set GOGCCFLAGS=-m64 -mthreads -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=C:\Users\ADMINI~1\AppData\Local\Temp\go-build2970026386=/tmp/go-build -gno-record-gcc-switches
aleass commented 5 months ago

my code, call the SystrayInit function in main func

package service

import (
    "embed"
    "fmt"
    "github.com/getlantern/systray"
    "log"
    "os"
    "syscall"
    "time"
    "wg-tag-printer-service/src/common"
)

//go:embed embed/run.ico
var logFiles embed.FS

// SystrayInit
//
//  @Description: 托盘功能初始化
func SystrayInit() {
    go systray.Run(onReady, nil)
}

// onReady
//
//  @Description: 准备工作
func onReady() {
    raw, _ := logFiles.ReadFile("embed/run.ico")
    systray.SetIcon(raw)
    systray.SetTitle(common.ManagerToolTitle)
    systray.SetTooltip(common.ManagerToolTitle)
    //添加菜单
    addMenuItem()
}

// addMenuItem
//
//  @Description: 添加菜单键
func addMenuItem() {
    //窗口
    showWindow := systray.AddMenuItem("打开窗口", "打开窗口")
    hideWindow := systray.AddMenuItem("隐藏窗口", "隐藏窗口")
    //退出
    quitEvent := systray.AddMenuItem("退出", "关闭打印工具程序")

    //dll
    kernel32 := syscall.NewLazyDLL("kernel32.dll")
    getConsoleWindows := kernel32.NewProc("GetConsoleWindow")
    consoleHandle, r2, err := getConsoleWindows.Call()
    if consoleHandle == 0 {
        fmt.Println("Error call GetConsoleWindow: ", consoleHandle, r2, err.Error())
    }

    user32 := syscall.NewLazyDLL("user32.dll")
    showWindowAsync := user32.NewProc("ShowWindowAsync")

    const (
        hideWindows uintptr = 0 //隐藏窗口并激活另一个窗口。
        showWindows uintptr = 5 //激活窗口并以当前大小和位置显示窗口。
    )

    //启动默认隐藏
    go func() {
        //查看是否启动成功
        fmt.Println("--------------------------5s 后自动隐藏窗口 -------------------------")
        time.Sleep(time.Second * 5)
        windowsOp(hideWindow, showWindowAsync, consoleHandle, hideWindows)
    }()

    go func() {
        for {
            select {
            case <-quitEvent.ClickedCh:
                quitEventFunc()
            case <-showWindow.ClickedCh:
                windowsOp(showWindow, showWindowAsync, consoleHandle, showWindows)
            case <-hideWindow.ClickedCh:
                windowsOp(hideWindow, showWindowAsync, consoleHandle, hideWindows)
            }
        }
    }()
}

// quitEventFunc
//
//  @Description: 退出事件
func quitEventFunc() {
    log.Println(common.ManagerToolTitle + " 退出")
    common.Logger.Debug(common.ManagerToolTitle + " 退出")

    // 杀旧进程
    common.KillProcess(common.ExecFileName)
    //由于是go systray,所以在这里直接退出
    os.Exit(0)
    //systray.Quit()
}

// hideWindows
//
//  @Description: 隐藏事件
//  @param mSwitchWindow
//  @param showWindowAsync
//  @param consoleHandle
func windowsOp(mSwitchWindow *systray.MenuItem, showWindowAsync *syscall.LazyProc, consoleHandle uintptr, nCmdShow uintptr) {
    mSwitchWindow.Disable()
    mSwitchWindow.Enable()
    r1, r2, err := showWindowAsync.Call(consoleHandle, nCmdShow)
    if r1 != 1 {
        log.Printf("Error call ShowWindow @SW_SHOW:%s,r1:%d,r2:%d", err.Error(), uint64(r1), uint64(r2))
        common.Logger.Error(fmt.Sprintf("Error call ShowWindow @SW_SHOW:%s,r1:%d,r2:%d", err.Error(), uint64(r1), uint64(r2)))
    }
}
wsczx commented 3 months ago

func Get_Systray() { runtime.LockOSThread() defer runtime.UnlockOSThread()

Recoverr(func() {
    systray.Run(onReady, onExit)
})

}

func Recoverr(fn func()) { defer func() { if r := recover(); r != nil { log.Printf("Recovered from panic: %v\n%s", r, debug.Stack()) } }() fn() } func main() { go gui.Get_Systray() select {} }

zzt741 commented 1 month ago

@wsczx thanks, after I add runtime.LockOSThread() in the systray.Run's gorountine, it works good.