安装walk库 go get https://github.com/lxn/walk
安装编译时依赖的库(rsrc,官网给出的定义是"Tool for embedding binary resources in Go programs.",这个是把资源二进制文件打入到go程序中,比如下文的manifest文件) go get github.com/akavel/rsrc
.manifest后缀文件放在源码main函数同级目录. .maifest文件直接可以在walk官网拷贝,这里照搬过来。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="SomeFunkyNameHere" type="win32"/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
注:不能直接go run 或者 不使用rsrc否则会报错
rsrc -manifest test.manifest -o rsrc.syso
#有图标的话执行这个,没有执行上面那个就行
rsrc -manifest test.manifest -o rsrc.syso -ico zh.ico
package main
import (
"archive/zip"
"fmt"
"github.com/lxn/walk"
"github.com/lxn/walk/declarative"
"golang.org/x/text/encoding/simplifiedchinese"
"io"
"os"
)
/*
功能:UTF8 转 GBK
参数:UTF8 编码的字符串
返回值:GBK编码的字符串和错误信息
*/
func UTF8ToGBK(text string) (string, error) {
dst := make([]byte, len(text)*2)
tr := simplifiedchinese.GB18030.NewDecoder()
nDst, _, err := tr.Transform(dst, []byte(text), true)
if err != nil {
return text, err
}
return string(dst[:nDst]), nil
}
type Window interface {
ShowWindow() // 展示窗体界面
}
// 创建压缩解压缩的界面类
type ComWindow struct {
Window
*walk.MainWindow // 主窗体
}
//展示压缩,解压成功失败提示信息的界面类
type LabWindow struct {
Window
}
// 创建界面类对象
func Show(Window_Type string) {
var Win Window
switch Window_Type {
case "main_window":
Win = &ComWindow{}
case "lab_window":
Win = &LabWindow{}
default:
fmt.Println("参数传递错误")
}
Win.ShowWindow()
}
var labText *walk.Label // 用来展示提示信息的Label.
var Text string // 保存提示信息的。
// // 首先实现ShowWindow方法,展示出空白的窗口
func (comWindow *ComWindow) ShowWindow() {
var unzipEdit *walk.LineEdit // 选择“解压文件”文件文本框
var saveUnZipEdit *walk.LineEdit // 解压后文件存放路径的文本框
var zipEdit *walk.LineEdit // 用来展示要压缩的文件路径的文本框
var saveZipEdit *walk.LineEdit // 用来展示压缩后的文件的存放路径的文本框
var unzipButn *walk.PushButton // 选择解压文件按钮
var saveUnZipBtn *walk.PushButton // 创建用来选择解压后文件存放路径的按钮
var zipBtn *walk.PushButton // 选择要压缩文件的按钮
var saveZipBtn *walk.PushButton // 选择压缩后文件存放路径的按钮
var startUnZipBtn *walk.PushButton // 开始解压按钮
var startZipBtn *walk.PushButton // 开始压缩的按钮
pathWindow := new(ComWindow)
err := declarative.MainWindow{
AssignTo: &pathWindow.MainWindow, // 关联主窗体,表明创建主窗体
Title: "ZH-文件压缩", // 窗口的标题名称
MinSize: declarative.Size{480, 230}, // 指定窗口的宽度与高度
//布局。
Layout: declarative.HBox{}, // 水平布局的方式
Children: []declarative.Widget{
// 左边区域
declarative.Composite{
Layout: declarative.Grid{Columns: 2, Spacing: 10}, // 左边区域分为两列布局
Children: []declarative.Widget{
declarative.LineEdit{ // 表示的文本框
AssignTo: &unzipEdit, // 将创建好的文本框与变量关联,后面可以根据该变量获取文本框中的值。
Text: "请输入路径",
},
// 添加选择解压文件的按钮
declarative.PushButton{
AssignTo: &unzipButn,
Text: "选择解压文件",
OnClicked: func() {
// 匿名函数
//fmt.Println(unzipButn.Text())
// 弹出选择文件对话框
filePath := pathWindow.OpenFileManager()
unzipEdit.SetText(filePath) // 将返回的文件的路径赋值给文本框。
//fmt.Println(filePath)
},
},
// 创建展示解压后文件存放路径的文本框。
declarative.LineEdit{
AssignTo: &saveUnZipEdit,
Text: "解压后文件的路径",
ToolTipText: "请输入解压后文件的存放路径",
},
// 创建用来选择解压后文件存放路径的按钮。
declarative.PushButton{
AssignTo: &saveUnZipBtn,
Text: "选择保存路径",
OnClicked: func() {
filePath := pathWindow.OpenDirManager()
//fmt.Println(filePath)
saveUnZipEdit.SetText(filePath)
},
},
// 创建一个用来展示要压缩的文件的路径的文本框
declarative.LineEdit{
AssignTo: &zipEdit,
Text: "选择要压缩的文件的路径",
},
// 添加压缩文件的按钮
declarative.PushButton{
AssignTo: &zipBtn,
Text: "选择压缩文件",
OnClicked: func() {
filePath := pathWindow.OpenFileManager()
zipEdit.SetText(filePath)
},
},
// 添加压缩好的文件存放路径展示的文本框。
declarative.LineEdit{
AssignTo: &saveZipEdit,
Text: "请输入要压缩后的文件存放路径",
},
// 创建一格选择压缩后文件路径的按钮
declarative.PushButton{
AssignTo: &saveZipBtn,
Text: "选择保存",
OnClicked: func() {
filePath := pathWindow.OpenDirManager()
saveZipEdit.SetText(filePath)
},
},
// 用来展示压缩与解压缩后相应的提示信息
declarative.Label{
AssignTo: &labText,
Text: "",
},
},
},
// 右边区域
declarative.Composite{
Layout: declarative.Grid{Rows: 2, Spacing: 40},
Children: []declarative.Widget{
declarative.PushButton{
AssignTo: &startUnZipBtn,
Text: "开始解压",
OnClicked: func() {
// 解压文件,传递了压缩文件的路径和解压后文件存放的路径
pathWindow.StartToUnZip(unzipEdit.Text(), saveUnZipEdit.Text())
Text = "文件解压成功"
Show("lab_window")
//ASCII
//汉字转码:go中汉字采用的是 UTF8 编码,
// 而 Windows 系统中汉字采用的编码格式是 GBK,不转码的话,会出现中文文件名乱码的问题
},
},
declarative.PushButton{
AssignTo: &startZipBtn,
Text: "开始压缩",
OnClicked: func() {
pathWindow.StartToZip(zipEdit.Text(), saveZipEdit.Text())
},
},
},
},
},
}.Create() //创建窗口
if err != nil {
fmt.Println(err)
}
// 窗口的展示,需要通过坐标来指定。
pathWindow.SetX(650) //x坐标
pathWindow.SetY(300) //y坐标
pathWindow.Run() //运行窗口,才能将创建的窗口给用户展示出来
}
// 打开文件选择对话框
func (mv *ComWindow) OpenFileManager() (filePath string) {
// 1: 创建文件对话框的对象
dlg := new(walk.FileDialog)
dlg.Title = "选择文件"
dlg.Filter = "所有文档(*.*)|*.*|文本文档(*.txt)|*.txt"
// 2: 打开文件对话框
b, err := dlg.ShowOpen(mv) // 如果单击对话框中的“打开”按钮,返回true,否则返回false
if err != nil {
fmt.Println(err)
}
fmt.Println(b)
// 3: 获取选中的文件
filePath = dlg.FilePath // 获取选中的文件的路径
return filePath
}
// 打开浏览文件夹的窗口
func (mv *ComWindow) OpenDirManager() (filePath string) {
// 1: 创建对话框的对象
dlg := new(walk.FileDialog)
// 2: 打开窗口
_, err := dlg.ShowBrowseFolder(mv) // 展示浏览文件夹的窗口
if err != nil {
fmt.Println(err)
}
// 3: 获取选中的路径,并且返回
filePath = dlg.FilePath //获取选中的路径
return filePath
}
// 实现文件解压操作
func (mv *ComWindow) StartToUnZip(file string, saveFile string) {
// 1: 获取第一个文本框中,要解压的文件的路径,并且读取压缩文件中的内容。
reader, err := zip.OpenReader(file)
if err != nil {
fmt.Println(err)
}
defer reader.Close()
// 2: 循环遍历压缩包中的文件。
for _, file := range reader.File {
rc, err := file.Open() // 打开从压缩文件中获取到的文件或者是文件夹。
if err != nil {
fmt.Println(err)
}
defer rc.Close()
// 构建完整的文件夹或者是文件的存放位置(文件夹或者是文件存放路径+文件夹或者文件的名称)
// C:\Test\hh
newName := saveFile + file.Name
newName, err = UTF8ToGBK(newName) // 编码
if err != nil {
fmt.Println(err)
}
// 判断是否为文件夹。IsDir():如果是文件夹,该方法返回的值为true,否则为false.
if file.FileInfo().IsDir() {
// 创建文件夹
err := os.MkdirAll(newName, os.ModePerm)
if err != nil {
fmt.Println(err)
}
}
// 判断是否为文件
if !file.FileInfo().IsDir() {
f, err := os.Create(newName)
if err != nil {
fmt.Println(err)
}
defer f.Close()
// 读取压缩包中文件的内容,然后写入到新创建的文件中。
// read write
_, err1 := io.Copy(f, rc)
if err1 != nil {
fmt.Println(err)
}
}
}
// 3: 判断一下是否是文件夹,如果是文件夹,则创建
// 4: 如果读取取来的是文件,则创建文件。
}
// 将提示信息打印在label
func (lab *LabWindow) ShowWindow() {
labText.SetText(Text)
}
// 实现文件压缩操作
func (mv *ComWindow) StartToZip(filePath string, savePath string) {
// 1: 获取第四个文本框中的值,然后创建压缩文件。
d, err := os.Create(savePath)
if err != nil {
fmt.Println(err)
}
defer d.Close()
// 2: 获取第三个文本框中的值,打开该文件。
file, err := os.Open(filePath)
if err != nil {
fmt.Println(err)
}
defer file.Close()
// 3: 将压缩的文件写入到压缩包中。
// 3.1 要获取要压缩的文件的信息
info, err := file.Stat()
if err != nil {
fmt.Println(err)
}
header, err := zip.FileInfoHeader(info)
if err != nil {
fmt.Println(err)
}
// 3.2 将要压缩的文件写入到压缩包中。
w := zip.NewWriter(d) // 根据创建的压缩包,创建了一个Writer指针,通过该指针,可以对压缩包进行操作
defer w.Close()
writer, err := w.CreateHeader(header)
if err != nil {
fmt.Println(err)
}
io.Copy(writer, file)
}
func main() {
Show("main_window")
//TestFunc()
}
func TestFunc() {
// 在一个函数中再次创建一个函数,要用到匿名函数。
func() {
fmt.Println("bbb")
}() // 表示调用执行匿名函数
fmt.Println("aaa")
}
qq交流群