使用 Go 语言创建窗口





5.00/5 (7投票s)
本技巧介绍了如何使用 Win32 API 函数在 Go 编程语言中创建一个简单的窗口。
引言
本技巧介绍了如何使用 Win32 API 函数在 Go 编程语言中创建一个简单的窗口。
本技巧仅展示了在 Go 中创建简单窗口的步骤。有关 Go 语言的更多信息,您可以访问 Go 文档网站 - https://golang.ac.cn/doc。
Go 简介 (摘自 https://golang.ac.cn)
Go 是一种开源编程语言,可以轻松构建简单、可靠和高效的软件。
Go 具有表达力、简洁、清晰和高效的特点。其并发机制使其易于编写能够充分利用多核和网络机器的程序,而其新颖的类型系统则支持灵活和模块化的程序构造。Go 可以快速编译成机器码,但同时具有垃圾回收的便利性和运行时反射的强大功能。它是一种快速的、静态类型的、编译型语言,感觉就像是一种动态类型的、解释型语言。
Using the Code
我假设您具备 Win32 API 的基本知识。
对于这个项目,我使用了 1.5.1 64 位 版本的 Go。
要在 Go 语言中使用 Win32 API,我们需要 'w32
' 包。可以在 Git Hub 网站上找到该包 - https://github.com/AllenDang/w32
这是我们的窗口创建代码
Go 源文件中的第一个语句必须是包名。由于我们的程序是一个可执行程序,因此包名必须是 main
。它告诉 Go 编译器应该将该包编译成一个可执行程序,而不是一个共享库
package main
在 Go 中,import
关键字用于将包导入到其他包中。因此,我们使用 import
关键字以这种方式导入我们必要的包
import "./w32" // I had putted the w32 package inside the project source folder -
我们还需要导入以下包
import "syscall"
import "unsafe"
Unsafe
是 Go 语言的内置包。它提供用于低级编程的工具,包括违反类型系统的操作。我们需要它将 uintptr
类型转换为指针,并且该包包含一个名为 Sizeof
的函数。我们将使用 Sizeof
函数获取 WNDCLASSEX
结构的大小。
这是一个简单的 Windows 资源 ID 到 uint16
指针转换器函数。我们需要它将 IDI_APPLICATION
和 IDC_ARROW
常量传递给 LoadIcon
和 LoadCursor
函数参数。在 Go 中,类型转换表达式为 T(v),其中将值 v
转换为类型 T
func MakeIntResource(id uint16) (*uint16) {
return (*uint16)(unsafe.Pointer(uintptr(id)))
}
这是我们的窗口消息处理程序函数,它仅处理 WM_DESTROY
消息,以确保我们的窗口在 close
事件上正确关闭
func WndProc(hWnd w32.HWND, msg uint32, wParam, lParam uintptr) (uintptr) {
switch msg {
case w32.WM_DESTROY:
w32.PostQuitMessage(0)
default:
return w32.DefWindowProc(hWnd, msg, wParam, lParam)
}
return 0
}
以下 WinMain
函数创建我们的窗口,并运行一个标准的应用循环
func WinMain() int {
在名为 hInstance
的局部变量中获取我们的应用程序实例句柄。在 Go 语言中,:=
运算符同时用作声明和初始化
hInstance := w32.GetModuleHandle("")
由于 w32
包仅定义 Unicode (UTF16) 兼容的 WinAPI 函数,因此我们必须使用来自 syscall
包的 StringToUTF16Ptr
函数将 Go string
类型转换为 UTF16 指针
lpszClassName := syscall.StringToUTF16Ptr("WNDclass")
在这里,我们使用 'var
' 关键字声明变量
var wcex w32.WNDCLASSEX
赋值只需使用 '=
' 运算符即可完成
wcex.Size = uint32(unsafe.Sizeof(wcex))
wcex.Style = w32.CS_HREDRAW | w32.CS_VREDRAW
wcex.WndProc = syscall.NewCallback(WndProc)
wcex.ClsExtra = 0
wcex.WndExtra = 0
wcex.Instance = hInstance
wcex.Icon = w32.LoadIcon(hInstance, MakeIntResource(w32.IDI_APPLICATION))
wcex.Cursor = w32.LoadCursor(0, MakeIntResource(w32.IDC_ARROW))
wcex.Background = w32.COLOR_WINDOW + 11
在 Go 语言中,nil
等同于 NULL
。由于我们没有为窗口提供任何菜单,因此我们将 MenuName
字段分配为 nil
wcex.MenuName = nil
wcex.ClassName = lpszClassName
wcex.IconSm = w32.LoadIcon(hInstance, MakeIntResource(w32.IDI_APPLICATION))
在这里,我们使用 RegisterClassEx
函数注册我们的类,该函数来自 w32 包。我们将 wcex
变量的地址传递给其参数 -
w32.RegisterClassEx(&wcex)
然后,我们使用来自 w32
包的 CreateWindowEx
函数创建我们的窗口。我们的窗口大小将为 400x400
hWnd := w32.CreateWindowEx(
0, lpszClassName, syscall.StringToUTF16Ptr("Simple Go Window!"),
w32.WS_OVERLAPPEDWINDOW | w32.WS_VISIBLE,
w32.CW_USEDEFAULT, w32.CW_USEDEFAULT, 400, 400, 0, 0, hInstance, nil)
我们使用来自 w32
包的 ShowWindow
函数在屏幕上显示我们的窗口
w32.ShowWindow(hWnd, w32.SW_SHOWDEFAULT)
w32.UpdateWindow(hWnd)
以下代码将运行标准的应用循环,直到我们关闭窗口。它将尝试从我们的窗口获取消息
var msg w32.MSG
for {
if w32.GetMessage(&msg, 0, 0, 0) == 0 {
break
}
w32.TranslateMessage(&msg)
w32.DispatchMessage(&msg)
}
return int(msg.WParam)
}
这是我们的程序入口点函数。它调用 WinMain
函数来创建并显示我们的窗口
func main() {
WinMain()
return
}
现在我们有了我们的源代码。我使用了 main.go
作为源文件名。
使用以下命令编译源文件
go.exe build -ldflags "-H windowsgui" main.go
' -ldflags "-H windowsgui"
' 标志将从我们的应用程序中删除黑色的控制台窗口。
现在,运行 main.exe 文件,看看你的简单 Go 窗口!
给读者的请求
如果您对 Go 语言的新项目有任何想法,这将有助于人们更轻松地学习该语言,您可以通过评论告知我。
结论
Go 是一种非常棒的编程语言。我们应该明智地使用它,以便从中获得适当的好处。我希望本技巧对初学者程序员有所帮助。