教程六:go语言windows gui界面开发之walk 控件学习第五节之窗口

一、系统托盘显示

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()
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尘帝阁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值