• 模拟鼠标操作 按钮点击, 文本输入, 滚动条

  • 模拟: 按钮点击, 文本输入, 滚动条


        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
    }