一、系统托盘显示
1.1 实现思路:
-
第一步:首先创建*walk.MainWindow主页面实例mw;
-
第二步:创建*walk.NotifyIcon实例ni,并且与mw进行绑定;
-
第三步:ni.MouseDown().Attach()方法中实现托盘点击事件;
-
第四步:创建托盘菜单,新建*walk.Action对象,并添加在ni中即可,多个菜单选项时,重复该步;
-
第五步:点击关闭窗口时,弹出是否退出窗口,重写主界面关闭窗口按钮事件;
----------- 此处在如果不退出,则最小化托盘,实现代码就是mw.Hide(),同时重写 关闭串口按钮事件; -
第六步:左键点击托盘还原主界面,即在左键事件中绑定还原操作;
----------- 还原窗口实现策略就是mw.Show(); -
警告:退出功能如果是要整个程序退出,则需要使用os.Exit(0)关闭,否则只是退出了界面协程。
-
警告:程序退出时,必须执行ni.Dispose()释放图标,否则图标会延时逗留,比如使用了os.Exit(0),必须在这之前就执行ni.Dispose()。
1.2 效果图如下:
- 右下角通知窗口
- 托盘菜单
- 点击帮助后,只是让弹窗;
- 点击关闭按钮,弹出提示,此处截图时在其它代码中运行的,为了方便,故合在当前文章中,意在理解思路即可;
-
1.3 实现代码
// Copyright 2011 The Walk Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"log"
"os"
"github.com/lxn/walk"
)
func main() {
// We need either a walk.MainWindow or a walk.Dialog for their message loop.
// We will not make it visible in this example, though.
mw, err := walk.NewMainWindow()
if err != nil {
log.Fatal(err)
}
// We load our icon from a file.
icon, err := walk.Resources.Icon("img/stop.ico")
if err != nil {
log.Fatal(err)
}
// Create the notify icon and make sure we clean it up on exit.
ni, err := walk.NewNotifyIcon(mw)
if err != nil {
log.Fatal(err)
}
defer ni.Dispose()
// Set the icon and a tool tip text.
if err := ni.SetIcon(icon); err != nil {
log.Fatal(err)
}
if err := ni.SetToolTip("Click for info or use the context menu to exit."); err != nil {
log.Fatal(err)
}
// When the left mouse button is pressed, bring up our balloon.
// 当鼠标左键点击托盘时,执行该时间,右键事件也可以通过if在该函数流程中实现
ni.MouseDown().Attach(func(x, y int, button walk.MouseButton) {
if button != walk.LeftButton {
return
}
//此处左键点击托盘复原主界面
mw.Show()
if err := ni.ShowCustom(
"Walk NotifyIcon Example",
"There are multiple ShowX methods sporting different icons.",
icon); err != nil {
log.Fatal(err)
}
})
addHelpMenu(mw, ni)
addExitMenu(mw, ni)
// The notify icon is hidden initially, so we have to make it visible.
if err := ni.SetVisible(true); err != nil {
log.Fatal(err)
}
// Now that the icon is visible, we can bring up an info balloon.
if err := ni.ShowInfo("右下角弹窗标题", "右下角弹窗内容哦"); err != nil {
log.Fatal(err)
}
// 重写主界面右上角 关闭窗口 按钮事件
// 功能描述:点击右上角关闭按钮,弹窗提示是否退出,点击是退出,点击否则将主界面隐藏即最小化到托盘
// 实现思路:重写 关闭窗口事件,如果是退出,如果否则隐藏主界面,
// 注意:此处不想关闭界面是,必须将参数 canceled 值设置为true,反之;
// 此处注释原因:在其它代码中测试没有问题,但在当前代码中未测试,故此处注释
/* closeevent := mw.Closing()
closeevent.Attach(func(canceled *bool, reason walk.CloseReason) {
result := walk.MsgBox(mw, "退出", "是否退出?", walk.MsgBoxYesNo)
if result == walk.DlgCmdYes {
os.Exit(0)
} else {
*canceled = true
mw.Hide()
}
})*/
// Run the message loop.
mw.Run()
}
func addHelpMenu(mw *walk.MainWindow, ni *walk.NotifyIcon) {
helpAction := walk.NewAction()
if err := helpAction.SetText("帮助"); err != nil {
log.Fatal(err)
}
helpAction.Triggered().Attach(func() {
walk.MsgBox(mw, "帮助", "帮助信息", walk.MsgBoxIconInformation)
})
if err := ni.ContextMenu().Actions().Add(helpAction); err != nil {
log.Fatal(err)
}
}
func addExitMenu(mw *walk.MainWindow, ni *walk.NotifyIcon) {
// We put an exit action into the context menu.
exitAction := walk.NewAction()
if err := exitAction.SetText("退出"); err != nil {
log.Fatal(err)
}
exitAction.Triggered().Attach(func() {
walk.App().Exit(0)
ni.Dispose()
os.Exit(0)
})
if err := ni.ContextMenu().Actions().Add(exitAction); err != nil {
log.Fatal(err)
}
}
二、窗口属性设置
2.1 属性列表:
- 去使能最小化按钮
- 去使能最大化按钮
- 去使能关闭按钮
- 去使能调整大小
- 去使能位置移动
- 窗口居中
2.2 效果图如下:
2.3 代码如下
package main
import (
"log"
"github.com/lxn/win"
"github.com/lxn/walk"
. "github.com/lxn/walk/declarative"
)
type MyWindow struct {
*walk.MainWindow
hWnd win.HWND
minimizeBox *walk.CheckBox
maximizeBox *walk.CheckBox
closeBox *walk.CheckBox
sizeBox *walk.CheckBox
ni *walk.NotifyIcon
}
func (mw *MyWindow) SetMinimizeBox() {
if mw.minimizeBox.Checked() {
mw.addStyle(win.WS_MINIMIZEBOX)
return
}
mw.removeStyle(^win.WS_MINIMIZEBOX)
}
func (mw *MyWindow) SetMaximizeBox() {
if mw.maximizeBox.Checked() {
mw.addStyle(win.WS_MAXIMIZEBOX)
return
}
mw.removeStyle(^win.WS_MAXIMIZEBOX)
}
func (mw *MyWindow) SetSizePersistent() {
if mw.sizeBox.Checked() {
mw.addStyle(win.WS_SIZEBOX)
return
}
mw.removeStyle(^win.WS_SIZEBOX)
}
func (mw *MyWindow) addStyle(style int32) {
currStyle := win.GetWindowLong(mw.hWnd, win.GWL_STYLE)
win.SetWindowLong(mw.hWnd, win.GWL_STYLE, currStyle|style)
}
func (mw *MyWindow) removeStyle(style int32) {
currStyle := win.GetWindowLong(mw.hWnd, win.GWL_STYLE)
win.SetWindowLong(mw.hWnd, win.GWL_STYLE, currStyle&style)
}
func (mw *MyWindow) SetCloseBox() {
if mw.closeBox.Checked() {
win.GetSystemMenu(mw.hWnd, true)
return
}
hMenu := win.GetSystemMenu(mw.hWnd, false)
win.RemoveMenu(hMenu, win.SC_CLOSE, win.MF_BYCOMMAND)
}
func main() {
mw := new(MyWindow)
if err := (MainWindow{
AssignTo: &mw.MainWindow,
Title: "notify icon",
Size: Size{550, 380},
Layout: VBox{MarginsZero: true},
}.Create()); err != nil {
log.Fatal(err)
}
mw.hWnd = mw.Handle()
// 去使能最小化按钮
mw.removeStyle(^win.WS_MINIMIZEBOX)
// 去使能最大化按钮
mw.removeStyle(^win.WS_MAXIMIZEBOX)
// 去使能关闭按钮
hMenu := win.GetSystemMenu(mw.hWnd, false)
win.RemoveMenu(hMenu, win.SC_CLOSE, win.MF_BYCOMMAND)
// 去使能调整大小
mw.removeStyle(^win.WS_SIZEBOX)
// 去使能位置移动
hMenu = win.GetSystemMenu(mw.hWnd, false)
win.RemoveMenu(hMenu, win.SC_MOVE, win.MF_BYCOMMAND)
// 设置窗口居中
mw.MainWindow.SetX((int(win.GetSystemMetrics(0)) - mw.MainWindow.Width()) / 2)
mw.MainWindow.SetY((int(win.GetSystemMetrics(1)) - mw.MainWindow.Height()) / 2)
mw.Run()
}