模拟: 按钮点击, 文本输入, 滚动条
1. 仅在主进程中使用ipc监听renderLoadEnd事件
2. 在渲染进程中的app.SetOnRenderLoadEnd监听渲染进程页面加载结束事件,在这个事件里获取页面html元素位置和大小
3. html元素位置和大小获取之后触发主进程监听事件, 把要获取到的html元素位置和大小发送到主进程renderLoadEnd事件
4. 主进程renderLoadEnd事件被触发后使用渲染进程传递的元素数据模拟事件操作
模拟事件使用当前窗口chromium或者browser提供的函数
chromium.SendXXX 只能在主进程中使用
browser.SendXXX 可在主进程或渲染进程中直接使用
5. 最后主进程回复ipc消息给渲染进程
该示例在windows下表现较好,linux和mac输入事件键盘码需要转换以及中文问题
代码如下:
//【渲染进程】渲染结束 app.SetOnRenderLoadEnd(func(browser *cef.ICefBrowser, frame *cef.ICefFrame, httpStatusCode int32) { // 浏览器ID和通道ID, 用于回复给渲染进程使用 var ( browserId = browser.Identifier() channelId = frame.Identifier() ) if browserId != 1 { return } fmt.Println("渲染完成", browserId, channelId) // 创建 dom visitor visitor := cef.DomVisitorRef.New() // 通过VisitDom获取html元素的位置和大小 , SetOnVisit 函数只能在渲染进程中执行 visitor.SetOnVisit(func(document *cef.ICefDomDocument) { // html > body body := document.GetBody() //获取输入框的位置 kw := body.GetDocument().GetElementById("kw") // dom元素Rect集合数据发送到主进程 var doms = make(map[string]cef.TCefRect) doms["kw"] = kw.GetElementBounds() // 触发主进程ipc监听事件 ipc.EmitTarget("renderLoadEnd", target.NewTargetMain(), browserId, channelId, doms) }) // 调用该函数后, 执行SetOnVisit回调函数 frame.VisitDom(visitor) })
//渲染进程发过来的消息,我们拿到了搜索框开始做事情 ipc.On("renderLoadEnd", func(browserId int32, channelId int64, doms map[string]cef.TCefRect) { fmt.Println("渲染进程发过来大消息", doms) inputTextEvent("国产最棒", doms["kw"]) //中文 jj.Sleep(1000) inputEnterEvent(doms["kw"]) textareaWheelEvent(doms["kw"]) me := &cef.TCefMouseEvent{ Modifiers: consts.EVENTFLAG_MIDDLE_MOUSE_BUTTON, //鼠标中键按下 } for i := 0; i < 3; i++ { var y int32 = int32(i * 100) me.Y = y fmt.Println("滚轮滚动") newllqChromium.SendMouseWheelEvent(me, 1, y) jj.Sleep(2000) } // 回复到渲染进程执行成功, 触发是Go的事件. ipc.EmitTarget("replyMockIsSuccess", target.NewTarget(nil, browserId, channelId, target.TgGoSub)) })
var domXYCenter = func(bound cef.TCefRect) (int32, int32) { return bound.X + bound.Width/2, bound.Y + bound.Height/2 } // 模拟button点击事件 var buttonClickEvent = func(domRect cef.TCefRect) { // 鼠标事件 me := &cef.TCefMouseEvent{} // 设置元素坐标,元素坐标相对于窗口,这里取元素中间位置 me.X, me.Y = domXYCenter(domRect) // 模拟鼠标到指定位置 newllqChromium.SendMouseMoveEvent(me, false) // 模拟鼠标双击事件 // 左键点击按下1次 newllqChromium.SendMouseClickEvent(me, consts.MBT_LEFT, false, 1) // 左键点击抬起1次 newllqChromium.SendMouseClickEvent(me, consts.MBT_LEFT, true, 1) } // 模拟input输入 var inputTextEvent = func(value string, domRect cef.TCefRect) { // 点击, 获取焦点 buttonClickEvent(domRect) // 一个一个字符设置 for _, v := range value { newllqChromium.SendKeyEvent(keyPress(string(v))) } } //模拟输入回车键 var inputEnterEvent = func(domRect cef.TCefRect) { event := &cef.TCefKeyEvent{} var asciiCode int = 13 event.Kind = consts.KEYEVENT_CHAR event.WindowsKeyCode = t.Int32(asciiCode) event.FocusOnEditableField = 1 // 0=false, 1=true newllqChromium.SendKeyEvent(event) } // 模拟textarea滚动 var textareaWheelEvent = func(domRect cef.TCefRect) { // 点击, 获取焦点 buttonClickEvent(domRect) // 鼠标事件 me := &cef.TCefMouseEvent{ Modifiers: consts.EVENTFLAG_MIDDLE_MOUSE_BUTTON, //鼠标中键按下 } // 设置元素坐标,元素坐标相对于窗口,这里取元素中间位置 me.X, me.Y = domXYCenter(domRect) newllqChromium.SendMouseWheelEvent(me, -100, -100) } // 模拟按键输入 func keyPress(key string) *cef.TCefKeyEvent { utf8Key := &lcltypes.TUTF8Char{} utf8Key.SetString(key) event := &cef.TCefKeyEvent{} var asciiCode int fmt.Sscanf(utf8Key.ToString(), "%c", &asciiCode) fmt.Println("输入", key, asciiCode) event.Kind = consts.KEYEVENT_CHAR event.WindowsKeyCode = t.Int32(asciiCode) event.FocusOnEditableField = 1 // 0=false, 1=true return event }