前两天我讲了bun+webview,今天我讲一下GO+webview。
GO语言有好多第三方的webview包,我个人感觉好用的是
github.com/webview/webview_go
安装包:
go get github.com/webview/webview_go
我下面的例子包含了web框架和winAPI
// main.go
package main
import (
"io"
"os"
"unsafe"
"github.com/labstack/echo/v4"
"github.com/labstack/gommon/log"
webview "github.com/webview/webview_go"
)
const (
SW_MAXIMIZE = 3
SW_MINIMIZE = 6
SW_RESTORE = 9
)
var (
w webview.WebView
h unsafe.Pointer
)
var (
width = 1280
height = 720
scale = 1.0
)
func main() {
//Message_Box("标题", "内容", 64)
go func() {
e := echo.New()
e.Logger.SetLevel(log.OFF)
e.Logger.SetOutput(io.Discard)
e.Static("/", "app")
e.Start("127.0.0.1:60088")
}()
args := os.Args
if len(args) > 1 {
if args[1] == "--debug" {
w = webview.New(true)
} else {
os.Exit(0)
}
} else {
w = webview.New(false)
w.Init("document.addEventListener('keydown', function (event) {if ( (event.ctrlKey && event.key === 'r') || (event.ctrlKey && event.key === 'R') || event.key === 'F5') {event.preventDefault();}});")
w.Init("document.addEventListener('contextmenu', function(event) {event.preventDefault();});")
}
defer w.Destroy()
h = w.Window()
w.SetTitle("MATAVIEW")
w.SetSize(width, height, webview.HintNone)
w.Bind("mata_win_minimize", win_minimize)
w.Bind("mata_win_maximize", win_maximize)
w.Bind("mata_win_restore", win_restore)
w.Bind("mata_win_close", win_close)
w.Bind("mata_win_center", win_center)
w.Bind("mata_win_title", win_title)
w.Init("window.mata={}")
w.Init("window.mata.win={}")
w.Init("window.mata.win.close=mata_win_close")
w.Init("window.mata.win.minimize=mata_win_minimize")
w.Init("window.mata.win.maximize=mata_win_maximize")
w.Init("window.mata.win.restore=mata_win_restore")
w.Init("window.mata.win.center=mata_win_center")
w.Init("window.mata.win.title=mata_win_title")
w.Navigate("http://127.0.0.1:60088/")
var dpi, _ = Get_Dpi_For_System()
scale = float64(dpi) / 96
win_center()
w.Run()
}
func win_size(ww int, hh int) {
}
func win_title(title string) {
w.SetTitle(title)
}
func win_minimize() {
Show_Window(h, SW_MINIMIZE)
}
func win_maximize() {
Show_Window(h, SW_MAXIMIZE)
}
func win_restore() {
Show_Window(h, SW_RESTORE)
}
func win_close() {
w.Terminate()
}
func win_center() {
screenWidth, _ := Get_System_Metrics(0)
screenHeight, _ := Get_System_Metrics(1)
realwidth := float64(width) * scale
realheight := float64(height) * scale
x := (screenWidth - int(realwidth)) / 2
y := (screenHeight - int(realheight)) / 2
Set_Window_Pos(h, 0, x, y, int(realwidth), int(realheight), 0)
}
// winapi.go
package main
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var (
user32 = syscall.NewLazyDLL("user32.dll")
kernel32 = syscall.NewLazyDLL("kernel32.dll")
FindWindow = user32.NewProc("FindWindowW")
ShowWindow = user32.NewProc("ShowWindow")
GetWindowRect = user32.NewProc("GetWindowRect")
GetSystemMetrics = user32.NewProc("GetSystemMetrics")
SetWindowPos = user32.NewProc("SetWindowPos")
GetDpiForSystem = user32.NewProc("GetDpiForSystem")
GetDpiForWindow = user32.NewProc("GetDpiForWindow")
SetWindowLongW = user32.NewProc("SetWindowLongW")
)
const (
GWL_STYLE = -16
WS_MAXIMIZEBOX = 0x00010000
)
func Set_Window_LongW(hwnd unsafe.Pointer, nIndex int, dwNewLong float64) (uintptr, uintptr, error) {
ret, ret2, err := SetWindowLongW.Call(uintptr(hwnd), uintptr(nIndex), uintptr(dwNewLong))
return ret, ret2, err
}
func Show_Window(hwnd unsafe.Pointer, show int) error {
ret, _, err := ShowWindow.Call(uintptr(hwnd), uintptr(show))
if ret == 0 {
return err
}
return nil
}
func Set_Window_Pos(hwnd unsafe.Pointer, hwndInsertAfter uintptr, x, y, cx, cy int, flags uint) error {
ret, _, err := SetWindowPos.Call(
uintptr(hwnd),
hwndInsertAfter,
uintptr(x),
uintptr(y),
uintptr(cx),
uintptr(cy),
uintptr(flags),
)
if ret == 0 {
return err
}
return nil
}
func Ge_Window_Rect(hwnd unsafe.Pointer) (rect struct{ Left, Top, Right, Bottom int }, err error) {
ret, _, err := GetWindowRect.Call(uintptr(hwnd), uintptr(unsafe.Pointer(&rect)))
if ret == 0 {
return rect, err
}
return rect, nil
}
func Get_System_Metrics(nIndex int) (int, error) {
ret, _, err := GetSystemMetrics.Call(uintptr(nIndex))
if ret == 0 {
return 0, err
}
return int(ret), nil
}
func Get_Dpi_For_System() (uint, error) {
ret, _, err := GetDpiForSystem.Call()
if ret == 0 {
return 0, err
}
return uint(ret), nil
}
func Get_Dpi_For_Window(hwnd unsafe.Pointer) (uint, error) {
ret, _, err := GetDpiForWindow.Call(uintptr(hwnd))
if ret == 0 {
return 0, err
}
return uint(ret), nil
}
func Message_Box(title string, message string, utype uint32) {
hwnd := windows.HWND(0)
ptitle, _ := syscall.UTF16PtrFromString(title)
pmessage, _ := syscall.UTF16PtrFromString(message)
windows.MessageBox(hwnd, pmessage, ptitle, utype)
}
如果你是我的老粉丝,你可以看出来这个就是我之前发布的MATAVIEW
下面是 精简版 MATAVIEW LITE源码
// main.go
package main
import (
"strconv"
"time"
"github.com/labstack/echo"
webview "github.com/webview/webview_go"
)
var w webview.WebView
func main() {
go func() {
e := echo.New()
e.Debug = false
e.HideBanner = true
e.DisableHTTP2 = true
e.Static("/", "./")
e.Start("127.0.0.1:60088")
}()
now := time.Now()
timestamp := strconv.FormatInt(now.UnixNano(), 10)
w = webview.New(false)
defer w.Destroy()
w.Init("document.addEventListener('keydown', function (event) {if ( (event.ctrlKey && event.key === 'r') || (event.ctrlKey && event.key === 'R') || event.key === 'F5') {event.preventDefault();}});")
w.Init("document.addEventListener('contextmenu', function(event) {event.preventDefault();});")
w.Bind("win_size", win_size)
w.Bind("win_close", win_close)
w.Bind("win_title", win_title)
w.Navigate("http://127.0.0.1:60088/?timestamp=" + timestamp)
w.Run()
}
func win_size(width int, height int, htype int) {
if htype == 0 {
w.SetSize(width, height, webview.HintNone)
} else {
w.SetSize(width, height, webview.HintFixed)
}
}
func win_close() {
w.Terminate()
}
func win_title(title string) {
w.SetTitle(title)
}
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button onclick="win_size(800,480,1)">修改大小</button>
<button onclick="win_title('新标题')">修改标题</button>
<button onclick="win_close()">关闭窗口</button>
<pre><code>
win_size(长,宽,锁定)
win_title(标题)
win_close()
</code></pre>
<div>MATAVIEW LITE是MATAVIEW的精简版,只保留三个函数,程序是静态编译,只包含HTTP静态服务器和WEBVIEW2(还是要安装webview2 runtime,WIN10 2004版本及其以上自带),减少杀软误杀的几率。</div>
<br>
<div>下载地址:https://share.weiyun.com/uhgAsAKI</div>
<script>
win_title("MATAVIEW LITE")
win_size(480, 800, 1)
</script>
</body>
</html>
LITE版取消了WINAPI接口,只保留了webview_go的接口和echo框架,其实如果你不需要echo也可以删除。