用 GO 开发一个windows桌面图形化软件入门

项目采用的是walk技术方案

一、初始化项目

创建一个文件夹比如demo,然后进入demo执行

go mod init demo

二、安装walk模块

go get github.com/lxn/walk
go get github.com/lxn/win

三、安装rsrc

安装:

go install github.com/akavel/rsrc

生成*.syso文件

rsrc -manifest main.manifest -o rsrc.syso

四、编写代码

main.go

var logger *log.Logger
var mainWindow *walk.MainWindow
var isLogin bool

func init() {
	logger = service.CreateLogService()
	isLogin = service.CheckLoginStatus(logger)
}
func main() {
	ui.CreateGUI(logger, mainWindow, isLogin)
}

ui

var loginGUIWidth, loginGUIHeight int

func init() {
	loginGUIWidth = 400
	loginGUIHeight = 100
}

func CreateGUI(logger *log.Logger, mw *walk.MainWindow, isLogin bool) {
	if !isLogin {
		LoginGUI(logger, mw)
	} else {
		MainGUI(logger)
	}
}

func LoginGUI(logger *log.Logger, mw *walk.MainWindow) {
	var username, password *walk.LineEdit
	mw, err := walk.NewMainWindow()
	if err != nil {
		panic(err)
		logger.Fatalln("LoginUI create error")
		return
	}
	MainWindow{
		AssignTo: &mw,
		Title:    "登录",
		Size:     Size{Width: loginGUIWidth, Height: loginGUIHeight},
		Layout:   VBox{},
		Children: []Widget{
			Composite{
				Layout: Grid{Columns: 2},
				Children: []Widget{
					Label{
						Text: "                            用户名:",
					},
					LineEdit{
						AssignTo: &username,
						MaxSize:  Size{Width: 150, Height: 40},
					},
				},
			},
			Composite{
				Layout: Grid{Columns: 2},
				Children: []Widget{
					Label{
						Text: "                            密    码:",
					},
					LineEdit{
						AssignTo:     &password,
						MaxSize:      Size{Width: 150, Height: 40},
						PasswordMode: true,
					},
				},
			},
			Composite{
				Layout: HBox{},
				Children: []Widget{
					PushButton{
						Text:    "登录",
						MaxSize: Size{Width: 50, Height: 40},
						OnClicked: func() {
							flag := service.LoginService(username.Text(), password.Text())
							if flag {
								service.SaveLoginStatus(logger)
								mw.Close()
								MainGUI(logger)
							} else {
								walk.MsgBox(mw, "错误", "用户名或密码错误", walk.MsgBoxIconError)
							}
						},
					},
				},
			},
		},
	}.Create()
	setWindowMaxDisable(mw)
	setWindowSizeDisable(mw)
	setWindowIcon(logger, mw)
	setOriginLocation(mw, loginGUIWidth, loginGUIHeight)
	setSysTray(logger, mw)
	// setSysNotification(logger, mw, "syscloud", "正在连接中")
}

// 禁用窗口最大化
func setWindowMaxDisable(mw *walk.MainWindow) {
	hwnd := mw.Handle()
	currStyle := win.GetWindowLong(hwnd, win.GWL_STYLE)
	win.SetWindowLong(hwnd, win.GWL_STYLE, currStyle&^win.WS_MAXIMIZEBOX)
}

// 禁用窗口大小修改
func setWindowSizeDisable(mw *walk.MainWindow) {
	hwnd := mw.Handle()
	currStyle := win.GetWindowLong(hwnd, win.GWL_STYLE)
	win.SetWindowLong(hwnd, win.GWL_STYLE, currStyle&^win.WS_SIZEBOX)
}

func MainGUI(logger *log.Logger) {
	mw, err := walk.NewMainWindow()
	MainWindow{
		AssignTo: &mw,
		Title:    "主窗口",
		Size:     Size{Width: loginGUIWidth, Height: loginGUIHeight},
		Layout:   VBox{},
		Children: []Widget{
			Composite{
				Layout: Grid{Columns: 2},
				Children: []Widget{
					Label{
						Text: "                        主窗口信息:",
					},
					LineEdit{
						MaxSize:  Size{Width: 150, Height: 40},
						Text:     "这是主窗口",
						ReadOnly: true,
					},
				},
			},
		},
	}.Create()
	if err != nil {
		walk.MsgBox(mw, "错误", "程序打开失败", walk.MsgBoxIconError)
		walk.App().Exit(0)
		return
	}
	// mw.SetVisible(true)
	setSysTray(logger, mw)
	// setSysNotification(logger, mw, "syscloud", "正在连接中")
}

// 设置窗口初始位置
func setOriginLocation(mw *walk.MainWindow, width int, height int) {
	mw.SetX(int(win.GetSystemMetrics(win.SM_CXSCREEN))/2 - width/2)
	mw.SetY(int(win.GetSystemMetrics(win.SM_CYSCREEN))/2 - height/2)
}

// 设置icon
func setWindowIcon(logger *log.Logger, mw *walk.MainWindow) {
	icon := getIcon(logger)
	mw.SetIcon(icon)
}

// 获取icon
func getIcon(logger *log.Logger) walk.Image {
	icon, err := walk.Resources.Image("resource/icon.ico")
	if err != nil {
		logger.Println("ERROR:获取icon失败", err)
	}
	return icon
}

// 设置系统托盘
func setSysTray(logger *log.Logger, mw *walk.MainWindow) {
	notifyIcon, err := walk.NewNotifyIcon(mw)
	if nil != err {
		logger.Println("ERROR:设置提醒图标失败")
	}
	defer notifyIcon.Dispose()
	icon := getIcon(logger)
	err = notifyIcon.SetIcon(icon)
	if nil != err {
		logger.Println("ERROR:设置图标失败")
	}
	notifyIcon.SetVisible(true)
	if err := notifyIcon.SetToolTip("syscloud客户端"); err != nil { // 设置系统托盘悬浮信息
		logger.Println("ERROR:设置悬浮信息失败", err)
	}
	setConnectMenu(logger, notifyIcon)
	setDisconnectMenu(logger, notifyIcon)
	setExitMenu(logger, notifyIcon)
	notifyIcon.ShowInfo("syscloud", "正在连接中")
	// notifyIcon.ShowInfo("syscloud", "连接成功")
	mw.Run()
}

// 系统托盘右键菜单(退出)
func setExitMenu(logger *log.Logger, ni *walk.NotifyIcon) {
	exitAction := walk.NewAction()
	if err := exitAction.SetText("退出"); err != nil {
		logger.Println(err)
	}
	//Exit 实现的功能
	exitAction.Triggered().Attach(func() { walk.App().Exit(0) })
	if err := ni.ContextMenu().Actions().Add(exitAction); err != nil {
		logger.Println(err)
	}
}

// 系统托盘右键菜单(连接)
func setConnectMenu(logger *log.Logger, ni *walk.NotifyIcon) {
	connectAction := walk.NewAction()
	if err := connectAction.SetText("连接"); err != nil {
		logger.Println(err)
	}
	connectAction.Triggered().Attach(func() {
		// 连接功能
		service.ConnectService(logger)
	})
	if err := ni.ContextMenu().Actions().Add(connectAction); err != nil {
		logger.Println(err)
	}
}

// 系统托盘右键菜单(断开)
func setDisconnectMenu(logger *log.Logger, ni *walk.NotifyIcon) {
	disconnectAction := walk.NewAction()
	if err := disconnectAction.SetText("断开"); err != nil {
		logger.Println(err)
	}
	disconnectAction.Triggered().Attach(func() {
		// 断开功能
		service.DisconnectService(logger)
	})
	if err := ni.ContextMenu().Actions().Add(disconnectAction); err != nil {
		logger.Println(err)
	}
}

五、界面效果

登录

主界面

更多代码:

imcc2022/clientDemo: 一个用walk框架写的windowsGUI示例(golang)/A windows GUI demo written by walk framework(golang) (github.com)

相关推荐
齐 飞2 分钟前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
童先生15 分钟前
Go 项目中实现类似 Java Shiro 的权限控制中间件?
开发语言·go
lulu_gh_yu16 分钟前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
LunarCod19 分钟前
WorkFlow源码剖析——Communicator之TCPServer(中)
后端·workflow·c/c++·网络框架·源码剖析·高性能高并发
Re.不晚40 分钟前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
老秦包你会42 分钟前
Qt第三课 ----------容器类控件
开发语言·qt
凤枭香1 小时前
Python OpenCV 傅里叶变换
开发语言·图像处理·python·opencv
ULTRA??1 小时前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
码农派大星。1 小时前
Spring Boot 配置文件
java·spring boot·后端
远望清一色1 小时前
基于MATLAB的实现垃圾分类Matlab源码
开发语言·matlab