本文介绍在Energy中如何像浏览器一样控制状态, 页面的加载、前进、后退、刷新、暂停刷新
前提-需要安装好开发环境参考: 教程一 环境安装
创建应用
- 开发环境中 MacOSX平台必须在"GlobalCEFInit"之前设置CEF
- 设置使用CEF 和 CEF框架目录,生成开发执行应用程序包
- macapp.MacApp.IsCEF(common.IsDarwin())
- 全局初始化 每个应用都必须调用的
- cef.GlobalCEFInit(&libs, &resources)
- 可选的应用配置
- cfg := cef.NewApplicationConfig()
- 指定chromium的二进制包框架根目录, 不指定为当前程序执行目录
- 环境变量ENERGY_HOME="/app/cefframework" 配置框架所在目录
if common.IsWindows() {
//SetFrameworkDirPath 或 配置环境变量 ENERGY_HOME
//cfg.SetFrameworkDirPath("D:\\app.exe\\energy\\chromium64")
} else if common.IsLinux() {
//cfg.SetFrameworkDirPath("/home/sxm/app/swt/energy/chromium")
}
-
创建应用
- cef.NewApplication(cfg)
-
主进程窗口初始化函数
- src.MainBrowserWindow()
package main
import ( "embed" "github.com/energye/energy/cef" "github.com/energye/energy/common" "github.com/energye/energy/example/browser-control/src" "github.com/energye/golcl/pkgs/macapp" )
//go:embed resources var resources embed.FS
//go:embed libs var libs embed.FS
func main() { //开发环境中 MacOSX平台必须在"GlobalCEFInit"之前设置CEF //设置使用CEF 和 CEF框架目录,生成开发执行应用程序包 macapp.MacApp.IsCEF(common.IsDarwin()) //环境变量 ENERGY_HOME="/app/cefframework" 配置框架所在目录 //全局初始化 每个应用都必须调用的 cef.GlobalCEFInit(&libs, &resources) //可选的应用配置 cfg := cef.NewApplicationConfig() //指定chromium的二进制包框架根目录, //不指定为当前程序执行目录 if common.IsWindows() { //SetFrameworkDirPath 或 配置环境变量 ENERGY_HOME //cfg.SetFrameworkDirPath("D:\app.exe\energy\chromium64") } else if common.IsLinux() { //cfg.SetFrameworkDirPath("/home/sxm/app/swt/energy/chromium") } //创建应用 cefApp := cef.NewApplication(cfg) //主进程窗口 src.MainBrowserWindow()
//运行应用 cef.Run(cefApp)}
系统UI和Energy
使用系统组件 golcl 创建控制相关按钮
初始主进程和窗口
-
在非主进程中有些代码是不必执行的。通过IsMain函数判断是否为主进程
- commons.Args.IsMain()
-
使用主浏览器的配置属性对浏览器进行了简单的配置
- cef.BrowserWindow.Config
-
使用ChromiumConfig配置开启右键菜单和开发者工具
- config.SetEnableMenu(true)
- config.SetEnableDevTools(true)
-
创建窗口时的回调函数 对浏览器事件设置,和窗口属性组件等创建和修改
-
cef.BrowserWindow.SetBrowserInit 窗口初始函数
-
在窗口初始函数中
- 设置更多的窗口属性
- 窗口的事件
- 浏览器的事件
-
cef.QueueAsyncCall 函数,在Linux中和操作UI相关的功能中,需要使用该函数包裹住,该函数会将被执行的函数移至主线程中执行。否则操作UI相关或Linux系统中会导致UI线程锁死 -
func controlUI 函数,在SetBrowserInit 函数中调用,主要创建主窗口内的系统UI组件package src
import ( "fmt" "github.com/energye/energy/cef" "github.com/energye/energy/common" "github.com/energye/golcl/lcl" "github.com/energye/golcl/lcl/types" )
//主浏览器窗口 func MainBrowserWindow() { //只有启动主进程才会继续执行 if !common.Args.IsMain() { return } //主窗口的配置 //指定一个URL地址,或本地html文件目录 cef.BrowserWindow.Config.DefaultUrl = "energy.yanghy.cn/" //窗口的标题 cef.BrowserWindow.Config.Title = "Energy - 浏览器控制" //窗口宽高 cef.BrowserWindow.Config.Width = 1024 cef.BrowserWindow.Config.Height = 768 //chromium配置 config := cef.NewChromiumConfig() config.SetEnableMenu(true) config.SetEnableDevTools(true) cef.BrowserWindow.Config.SetChromiumConfig(config) //创建窗口时的回调函数 对浏览器事件设置,和窗口属性组件等创建和修改 cef.BrowserWindow.SetBrowserInit(func(event *cef.BrowserEvent, browserWindow *cef.TCefWindowInfo) { //设置应用图标 这里加载的图标是内置到执行程序里的资源文件 lcl.Application.Icon().LoadFromFSFile("resources/icon.ico") //在窗体初始化时创建窗口内的组件 back, forward, stop, refresh, progressLabel, addr := controlUI(browserWindow) //页面加载处理进度 event.SetOnLoadingProgressChange(func(sender lcl.IObject, browser cef.ICefBrowser, progress float64) { //linux 更新UI组件必须使用 QueueAsyncCall 主线程异步同步 cef.QueueAsyncCall(func(id int) { //参数-进度 progressLabel.SetCaption(fmt.Sprintf("%v", progress100)) }) }) //页面加载状态,根据状态判断是否加载完成,和是否可前进后退 event.SetOnLoadingStateChange(func(sender lcl.IObject, browser *cef.ICefBrowser, isLoading, canGoBack, canGoForward bool) { //linux 更新UI组件必须使用 QueueAsyncCall 主线程异步同步 cef.QueueAsyncCall(func(id int) { //控制按钮状态 stop.SetEnabled(isLoading) refresh.SetEnabled(!isLoading) back.SetEnabled(canGoBack) forward.SetEnabled(canGoForward) }) }) event.SetOnAddressChange(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, url string) { cef.QueueAsyncCall(func(id int) { addr.SetText(url) }) }) }) //创建窗口之后对对主窗口的属性、组件或子窗口的创建 cef.BrowserWindow.SetBrowserInitAfter(func(browserWindow *cef.TCefWindowInfo) { fmt.Println("SetBrowserInitAfter") }) }
//控制组件UI //地址栏和控制按钮创建 func controlUI(browserWindow *cef.TCefWindowInfo) (goBack *lcl.TButton, goForward *lcl.TButton, stop *lcl.TButton, refresh *lcl.TButton, progressLabel *lcl.TLabel, addrBox *lcl.TComboBox) { window := browserWindow.Window //这里使用系统UI组件 //创建panel做为地址栏的父组件 addrPanel := lcl.NewPanel(window) //设置父组件 addrPanel.SetParent(window) addrPanel.SetAnchors(types.NewSet(types.AkLeft, types.AkTop, types.AkRight)) //设置锚点定位,让宽高自动根据窗口调整大小 addrPanel.SetHeight(25) addrPanel.SetWidth(window.Width()) //创建 按钮-后退 goBack = lcl.NewButton(addrPanel) //设置父组件 goBack.SetParent(addrPanel) goBack.SetCaption("后退") goBack.SetBounds(0, 0, 35, 25) goForward = lcl.NewButton(addrPanel) //设置父组件 goForward.SetParent(addrPanel) goForward.SetCaption("前进") goForward.SetBounds(35, 0, 35, 25) stop = lcl.NewButton(addrPanel) //设置父组件 stop.SetParent(addrPanel) stop.SetCaption("停止") stop.SetBounds(35+35, 0, 35, 25) refresh = lcl.NewButton(addrPanel) //设置父组件 refresh.SetParent(addrPanel) refresh.SetCaption("刷新") refresh.SetBounds(35+35+35, 0, 35, 25)
//创建下拉框 addrBox = lcl.NewComboBox(addrPanel) addrBox.SetParent(addrPanel) addrBox.SetLeft(35 + 35 + 35 + 35) //这里是设置左边距 上面按钮的宽度 addrBox.SetWidth(window.Width() - (35 + 35 + 35 + 35 + 35 + 35)) //宽度 减按钮的宽度 addrBox.SetAnchors(types.NewSet(types.AkLeft, types.AkTop, types.AkRight)) //设置锚点定位,让宽高自动根据窗口调整大小 addrBox.Items().Add("https://energy.yanghy.cn") addrBox.Items().Add("https://www.baidu.com") //显示加载进度 progressLabel = lcl.NewLabel(addrPanel) //设置父组件 progressLabel.SetParent(addrPanel) progressLabel.SetCaption("0") progressLabel.SetBounds(window.Width()-(35+35)-10, 3, 35, 25) progressLabel.SetAnchors(types.NewSet(types.AkTop, types.AkRight)) //设置锚点定位,让宽高自动根据窗口调整大小 goUrl := lcl.NewButton(addrPanel) //设置父组件 goUrl.SetParent(addrPanel) goUrl.SetCaption("GO") goUrl.SetBounds(window.Width()-35, 0, 35, 25) goUrl.SetAnchors(types.NewSet(types.AkTop, types.AkRight)) //设置锚点定位,让宽高自动根据窗口调整大小 //重新调整browser窗口的Parent属性 //重新设置了上边距,宽,高 window.WindowParent().SetAlign(types.AlNone) //重置对齐,默认是整个客户端 window.WindowParent().SetTop(25) window.WindowParent().SetHeight(window.Height() - 25) window.WindowParent().SetWidth(window.Width()) //设置锚点定位,让宽高自动根据窗口调整大小 //因为窗口大小已调整,这里不能使用 SetAlign 了 window.WindowParent().SetAnchors(types.NewSet(types.AkTop, types.AkLeft, types.AkRight, types.AkBottom)) //给按钮增加事件 goBack.SetOnClick(func(sender lcl.IObject) { browserWindow.Chromium().GoBack() }) goForward.SetOnClick(func(sender lcl.IObject) { browserWindow.Chromium().GoForward() }) stop.SetOnClick(func(sender lcl.IObject) { browserWindow.Chromium().StopLoad() }) refresh.SetOnClick(func(sender lcl.IObject) { browserWindow.Chromium().Reload() }) goUrl.SetOnClick(func(sender lcl.IObject) { var url = addrBox.Text() if url != "" { browserWindow.Chromium().LoadUrl(url) } }) return}
go run xx.go
或
go build
或
go build -ldflags “-H windowsgui -s -w”
说明
需要你自己下载编译好的框架二进制包,或使用energy命令行工具安装环境,参考教程CEF和Enregy使用
这里面用到了系统UI组件
- 首先创建了应用,应用创建属于不管主进程还是渲染进程(子进程)都要执行的代码, 通过NewApplicationConfig配置应用参数,需要你使用(SetFrameworkDirPath)指定框架目录,如果执行文件在框架目录中,则不需要指定.
- 创建主窗口,在CEF中主窗口是主进程,UI的主进程,也是brower的主进程,大多数业务逻辑都要在该进程中实现
- 在主进程中创建了窗口组件,按钮控制组件,事件监听,窗口属性设置等等.
控制事件
在回调函数BrowserWindow.SetBrowserInit设置事件监听
cef.BrowserWindow.SetBrowserInit(func(event *cef.BrowserEvent, browserWindow *cef.TCefWindowInfo)
设置加载进度改变事件
event.SetOnLoadingProgressChange(func(sender lcl.IObject, browser *cef.ICefBrowser, progress float64)
设置页面加载状态事件
event.SetOnLoadingStateChange(func(sender lcl.IObject, browser *cef.ICefBrowser, isLoading, canGoBack, canGoForward bool)