Skip to content

效果图

context-menu

自定义右键菜单

go
package main

import (
	"embed"
	"fmt"
	"github.com/energye/energy/v2/cef"
	"github.com/energye/energy/v2/cef/ipc"
	"github.com/energye/energy/v2/common"
	"github.com/energye/energy/v2/consts"
	"github.com/energye/energy/v2/pkgs/assetserve"
	"github.com/energye/golcl/lcl"
)

//go:embed resources
var resources embed.FS

func main() {
	//全局初始化 每个应用都必须调用的
	cef.GlobalInit(nil, &resources)
	//创建应用
	cefApp := cef.NewApplication()
	//指定一个URL地址,或本地html文件目录
	cef.BrowserWindow.Config.Url = "http://localhost:22022/index.html"
	if common.IsLinux() {
		cef.BrowserWindow.Config.IconFS = "resources/icon.png"
	} else {
		cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
	}
	//主进程启动成功之后回调
	cef.SetBrowserProcessStartAfterCallback(func(b bool) {
		fmt.Println("主进程启动 创建一个内置http服务")
		//通过内置http服务加载资源
		server := assetserve.NewAssetsHttpServer()
		server.PORT = 22022
		server.AssetsFSName = "resources" //必须设置目录名
		server.Assets = &resources
		go server.StartHttpServer()
	})
	//在主窗口初始化监听浏览器事件
	cef.BrowserWindow.SetBrowserInit(func(event *cef.BrowserEvent, window cef.IBrowserWindow) {
		var (
			menuId01           consts.MenuId
			menuId02           consts.MenuId
			menuId03           consts.MenuId
			menuId0301         consts.MenuId
			menuId0302         consts.MenuId
			menuIdCheck        consts.MenuId
			isMenuIdCheck      = true
			menuIdEnable       consts.MenuId
			isMenuIdEnable     = true
			menuIdEnableCtl    consts.MenuId
			menuIdRadio101     consts.MenuId
			menuIdRadio102     consts.MenuId
			menuIdRadio103     consts.MenuId
			radioDefault1Check consts.MenuId
			menuIdRadio201     consts.MenuId
			menuIdRadio202     consts.MenuId
			menuIdRadio203     consts.MenuId
			radioDefault2Check consts.MenuId
		)
		//右键弹出菜单
		event.SetOnBeforeContextMenu(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, params *cef.ICefContextMenuParams, model *cef.ICefMenuModel) {
			//既然是自定义,当然要去除之前事先定义好的
			model.Clear()
			//开始创建菜单,每个菜单项都有自己的ID, 所以要先定义一个能保存这些菜单项的ID的变量
			fmt.Printf("%+v\n", params)
			//注意: 每个菜单项的ID有固定的 ID 生成函数
			//获取一个菜单项ID
			menuId01 = model.CefMis.NextCommandId()
			model.AddItem(menuId01, "菜单一 html 文字变红色")
			menuId02 = model.CefMis.NextCommandId()
			model.AddItem(menuId02, "菜单二 html 文字变绿色")
			menuId03 = model.CefMis.NextCommandId()
			menu03 := model.AddSubMenu(menuId03, "菜单三 带有子菜单")
			menuId0301 = model.CefMis.NextCommandId()
			menu03.AddItem(menuId0301, "菜单三的子菜单一 ")
			menuId0302 = model.CefMis.NextCommandId()
			menu03.AddItem(menuId0302, "菜单三的子菜单二")
			model.AddSeparator()
			//check
			menuIdCheck = model.CefMis.NextCommandId()
			model.AddCheckItem(menuIdCheck, "这是一个checkItem-好像就windows有效")
			model.SetChecked(menuIdCheck, isMenuIdCheck)
			//enable
			model.AddSeparator()
			menuIdEnable = model.CefMis.NextCommandId()
			if isMenuIdEnable {
				model.AddItem(menuIdEnable, "菜单-已启用")
				model.SetColor(menuIdEnable, consts.CEF_MENU_COLOR_TEXT, consts.NewCefARGB(255, 111, 12, 200))
			} else {
				model.AddItem(menuIdEnable, "菜单-已禁用")
			}
			model.SetEnabled(menuIdEnable, isMenuIdEnable)
			menuIdEnableCtl = model.CefMis.NextCommandId()
			model.AddItem(menuIdEnableCtl, "启用上面菜单")
			//为什么要用Visible而不是不创建这个菜单? 因为菜单项的ID是动态的啊。
			model.SetVisible(menuIdEnableCtl, !isMenuIdEnable)
			if !isMenuIdEnable {
				model.SetColor(menuIdEnableCtl, consts.CEF_MENU_COLOR_TEXT, consts.NewCefARGB(255, 222, 111, 0))
			}
			model.AddSeparator()
			//radio 1组
			menuIdRadio101 = model.CefMis.NextCommandId()
			menuIdRadio102 = model.CefMis.NextCommandId()
			menuIdRadio103 = model.CefMis.NextCommandId()
			model.AddRadioItem(menuIdRadio101, "单选按钮 1 1组", 1001)
			model.AddRadioItem(menuIdRadio102, "单选按钮 2 1组", 1001)
			model.AddRadioItem(menuIdRadio103, "单选按钮 3 1组", 1001)
			if radioDefault1Check == 0 {
				radioDefault1Check = menuIdRadio101
			}
			model.SetChecked(radioDefault1Check, true)
			model.AddSeparator()
			//radio 2组
			menuIdRadio201 = model.CefMis.NextCommandId()
			menuIdRadio202 = model.CefMis.NextCommandId()
			menuIdRadio203 = model.CefMis.NextCommandId()
			model.AddRadioItem(menuIdRadio201, "单选按钮 1 2组", 1002)
			model.AddRadioItem(menuIdRadio202, "单选按钮 2 2组", 1002)
			model.AddRadioItem(menuIdRadio203, "单选按钮 3 2组", 1002)
			if radioDefault2Check == 0 {
				radioDefault2Check = menuIdRadio201
			}
			model.SetChecked(radioDefault2Check, true)
		})
		//右键菜单项命令
		event.SetOnContextMenuCommand(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, params *cef.ICefContextMenuParams, menuId consts.MenuId, eventFlags uint32, result *bool) {
			fmt.Printf("params: %+v\n", params)
			fmt.Println("menuId: ", menuId, eventFlags, *result)
			//在这里处理某个菜单项的点击事件所触发的命令,这里的命令对应着一个菜单项的ID
			var clickMenuId = 0
			switch menuId {
			case menuId01:
				clickMenuId = 1
			case menuId02:
				clickMenuId = 2
			case menuIdEnable:
				isMenuIdEnable = !isMenuIdEnable
			case menuIdCheck:
				isMenuIdCheck = !isMenuIdCheck
			case menuIdEnableCtl:
				isMenuIdEnable = true
			case menuIdRadio101, menuIdRadio102, menuIdRadio103:
				radioDefault1Check = menuId
			case menuIdRadio201, menuIdRadio202, menuIdRadio203:
				radioDefault2Check = menuId
			}
			ipc.Emit("menu", clickMenuId, fmt.Sprintf("菜单 %d 随便传点什么吧 但是,字符串参数字符串参数字符串参数字符串参数字符串参数字符串参数字符串参数.", menuId))
			//*result = true
		})
	})
	//运行应用
	cef.Run(cefApp)
}

HTML示例代码

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>browser-context-menu</title>
    <style>
    </style>
    <script type="application/javascript">
        ipc.on('menu', function (menuId, param2) {
            console.log(menuId, param2);
            let menu = document.getElementById("menu")
            if (menuId === 1) {
                menu.style.color = "red"
            } else if (menuId === 2) {
                menu.style.color = "green"
            } else {
                menu.innerHTML += param2 + "<br>"
            }
        })
    </script>
</head>
<body style="overflow: hidden;margin: 0px;padding: 0px;width: 100%;text-align: center;">
<h3 id="menu">自定义右键菜单</h3>
</body>
</html>