龙空技术网

golang 托盘菜单应用及打开系统默认浏览器

康宁细语 82

前言:

目前各位老铁们对“win10托盘图标”大约比较珍视,咱们都想要剖析一些“win10托盘图标”的相关文章。那么小编也在网上收集了一些关于“win10托盘图标””的相关知识,希望大家能喜欢,看官们快快来了解一下吧!

之前看到一个应用,用go语言编写,说是某某程序的windows图形化客户端,体验一下发现只是一个托盘,然后托盘菜单的控制面板功能直接打开本地浏览器访问程序启动的web server网页完成gui相关功能。顿时感觉,嗯,是个曲线绕开类似electron等框架的方法。

这种方式的好处是,可以把擅长写web服务的应用桌面化,当需要gui的时候,直接托盘菜单启动浏览器,完成相关功能后,直接关闭浏览器省内存。

我的gost-ui-3程序用electron编写,内部集成浏览器,安装包60-~85M,启动后内存占用超过100M,所以后面考虑节省资源的方式,可以使用托盘图标+默认浏览器的方式解决。

当然如果对 cgo 敏感的话,就不能用了,三个平台都依赖 cgo

1. golang 托盘图标的使用

因为最近常用的是windows,家里的mac已经吃灰很久了。所以暂时默认适配的是windows环境。理论上mac和linux上也是可以适配的。

最核心的是应用了 github.com/getlantern/systray 这个库。

一个最简单的示例如下:

注意提前准备好相应的图标文件

package mainimport (	_ "embed"	"fmt"	"github.com/getlantern/systray")// embed 指令直接读取icon文件并在编译时嵌入程序中////go:embed icon.icovar iconWin []byte// 托盘菜单描述,自定义,为了方便定义和事件管理type Menu struct {	Title   string	Tips    string	Icon    []byte	OnClick func(m *systray.MenuItem)}// 添加菜单func AddMenu(menu *Menu) *systray.MenuItem {	m := systray.AddMenuItem(menu.Title, menu.Tips)	if len(menu.Icon) > 0 {		m.SetIcon(menu.Icon)	}	go func() {		for range m.ClickedCh {			menu.OnClick(m)		}	}()	return m}// 添加checkbox菜单func AddCheckboxMenu(menu *Menu, checked bool) *systray.MenuItem {	m := systray.AddMenuItemCheckbox(menu.Title, menu.Tips, checked)	if len(menu.Icon) > 0 {		m.SetIcon(menu.Icon)	}	go func() {		for range m.ClickedCh {			menu.OnClick(m)		}	}()	return m}func main() {	systray.Run(onReady, onExit)}func onReady() {	systray.SetIcon(iconWin)	systray.SetTitle("托盘图标示例")	systray.SetTooltip("托盘图标示例提示")	// 选择框和动态菜单综合示例    AddCheckboxMenu(&Menu{		Title: "启动",		OnClick: func(m *systray.MenuItem) {			if m.Checked() {				m.SetTitle("启动")				m.Uncheck()			} else {				m.SetTitle("停止")				m.Check()			}		},	}, false)	// 添加退出菜单	AddMenu(&Menu{		Title: "退出",		Tips:  "退出程序",		OnClick: func(m *systray.MenuItem) {			systray.Quit()		},	})}func onExit() {	fmt.Printf("退出喽")}

同时看到一些可能在应用中需要用到的api方法如下

// 设置主托盘图标, 比如一个服务分别在启动状态和关闭状态使用不同的图标systray.SetTemplateIcon(_icon, _icon)// 菜单可以显示和隐藏systray.MenuItem.Show(); systray.MenuItem.Hide()// 菜单可禁止和启用systray.MenuItem.Disable(); systray.MenuItem.Enable()// 添加一组菜单的方式func AddMenuGroup(title string, sub []*Menu) {	boot := systray.AddMenuItem(title, "")	for _, v := range sub {		mi := boot.AddSubMenuItem(v.Title, v.Title)		_v := v		go func() {			for {				select {				case <-mi.ClickedCh:					_v.OnClick(mi)				}			}		}()	}}
2. 用 golang 打开默认浏览器

打开默认浏览器其实就是执行对应平台的系统命令。

结合我的托盘示例,一个完整的例子程序如下。主要看Open(uri string)方法。

//go:generate goversioninfopackage mainimport (    _ "embed"    "fmt"    "os/exec"    "runtime"    "github.com/getlantern/systray")//go:embed icon/icon.pngvar icon []byte//go:embed icon/icon_off.pngvar iconOff []byte//go:embed icon/icon.icovar iconWin []byte//go:embed icon/icon_off.icovar iconOffWin []byte//go:embed icon/logo.pngvar logo []byte// 不同平台打开浏览器对应的命令var commands = map[string]string{    "windows": "cmd",    "darwin":  "open",    "linux":   "xdg-open",}// 托盘菜单自定义数据结构type Menu struct {    Title   string    Tips    string    Icon    []byte    OnClick func(m *systray.MenuItem)}func main() {    systray.Run(onReady, onExit)}// 执行打开默认浏览器并访问指定uri的命令func Open(uri string) error {    run, ok := commands[runtime.GOOS]    if !ok {        return fmt.Errorf("don't know how to open things on %s platform", runtime.GOOS)    }    var cmd *exec.Cmd    if runtime.GOOS == "windows" {        cmd = exec.Command(run, `/c`, `start`, uri)		// 无console调用        cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}    } else {        // linux和mac下暂未测试        cmd = exec.Command(run, uri)    }    return cmd.Start()}// 添加一个常规菜单func AddMenu(menu *Menu) *systray.MenuItem {    m := systray.AddMenuItem(menu.Title, menu.Tips)    if len(menu.Icon) > 0 {        m.SetIcon(menu.Icon)    }    go func() {        for range m.ClickedCh {            menu.OnClick(m)        }    }()    return m}// 托盘启动时func onReady() {    systray.SetIcon(iconWin)    systray.SetTitle("托盘图标示例")    systray.SetTooltip("托盘图标示例提示")    // 打开一个浏览器网址    AddMenu(&Menu{        Title: "我的博客",        Tips: "blog.wavesxa.com",        OnClick: func(m *systray.MenuItem) {            Open(";)        },    })    // 退出菜单    AddMenu(&Menu{        Title: "退出",        Tips: "退出程序",        OnClick: func(m *systray.MenuItem) {            systray.Quit()        },    })}// 托盘退出时func onExit() {    fmt.Printf("退出喽")}

标签: #win10托盘图标 #linux系统打开浏览器的指令