如何在 Awesomium 中实现鼠标点击?

How do I implement mouse click in Awesomium?

我编写此代码是为了测试注入鼠标方法,但它对我不起作用。测试应该在 google 文本框搜索区域中单击,但该框永远不会突出显示。知道为什么吗?

Google 的页面确实加载了。代码运行(通过断点确认),但是没有任何反应。

public partial class Form1 : Form
    {
        private IWebView webView;
        public Form1()
        {
            InitializeComponent();
            initiate();

        }

        private void button1_Click(object sender, EventArgs e)
         {
            click(650, 405);
        }

        private async void initiate()
        {

            WebSession session = WebCore.CreateWebSession(
@"C:\SessionDataPath", WebPreferences.Default);
            webView = WebCore.CreateWebView(
      this.ClientSize.Width,
      this.ClientSize.Height, session, WebViewType.Window
     );
            webView.ParentWindow = this.Handle;
            webView.Source = new Uri("http://www.google.com");
            await Task.Delay(30000);
            click(650, 405);

        }

        public void click(int x, int y)
        {
            webView.InjectMouseMove(x, y);
            webView.InjectMouseDown(MouseButton.Left);
            webView.InjectMouseUp(MouseButton.Left);
        }
    }

我试图通过查看合适的 chromium class 让此代码与 chromium handle 一起工作,但它没有用

  private async Task<bool> clickCoorindate(Point point)
        {
            webView.FocusView();
            int x = point.X; // X coordinate of the click
            int y = point.Y; // Y coordinate of the click
            IntPtr handle = webView.ProcessHandle;
            StringBuilder className = new StringBuilder(100);
            while (className.ToString() != "Chrome_RenderWidgetHostHWND") // The class control for the browser
            {
                handle = GetWindow(handle, 5); // Get a handle to the child window
                GetClassName(handle, className, className.Capacity);
                if (className.ToString() == "Chrome_RenderWidgetHostHWND")
                    handle = Handle;

            }

            IntPtr lParam = (IntPtr)((y << 16) | x); // The coordinates
            IntPtr wParam = IntPtr.Zero; // Additional parameters for the click (e.g. Ctrl)
            const uint downCode = 0x201; // Left click down code
            const uint upCode = 0x202; // Left click up code
            const uint moveCode = 0x200;

            SendMessage(handle, downCode, wParam, lParam); // Mouse button down
            SendMessage(handle, upCode, wParam, lParam); // Mouse button up
            Thread.Sleep(20);
            SendMessage(handle, downCode, wParam, lParam); // Mouse button down
            SendMessage(handle, upCode, wParam, lParam); // Mouse button up

            return true;

        }

在我的 XNA 游戏中,我使用了很多 Awesomium,这是我在我的 awesomium 组件中实现的输入系统,它运行良好。 请注意,这只是我的 class 的一部分,因此有些方法不在这里,但不需要它们来理解该过程 基本上在我的线程中。基本上我挂钩到我的表单中的消息并将它们中继到 WebView。希望这有帮助

  public partial class BasicAwesomiumComponent : DrawableGameComponent {

  private delegate Int32 ProcessMessagesDelegate(Int32 code, Int32 wParam, ref Message lParam);

  private static class User32 {
     [DllImport("user32.dll", SetLastError = true)]
     internal static extern IntPtr SetWindowsHookEx(Int32 windowsHookId, ProcessMessagesDelegate function, IntPtr mod, Int32 threadId);

     [DllImport("user32.dll", SetLastError = true)]
     internal static extern Int32 UnhookWindowsHookEx(IntPtr hook);

     [DllImport("user32.dll", SetLastError = true)]
     internal static extern Int32 CallNextHookEx(IntPtr hook, Int32 code, Int32 wParam, ref Message lParam);

     [DllImport("user32.dll", SetLastError = true)]
     internal static extern Boolean TranslateMessage(ref Message message);

     [DllImport("user32.dll", CharSet = CharSet.Auto)]
     internal static extern IntPtr FindWindow(String className, String windowName);

     [DllImport("user32.dll", CharSet = CharSet.Auto)]
     internal static extern int RegisterWindowMessage(String msg);

     [DllImport("user32.dll", CharSet = CharSet.Auto)]
     internal static extern IntPtr SendMessage(HandleRef hWnd, Int32 msg, Int32 wParam, Int32 lParam);

     [DllImport("user32.dll", CharSet = CharSet.Auto)]
     internal static extern bool SystemParametersInfo(Int32 nAction, Int32 nParam, ref Int32 value, Int32 ignore);

     [DllImport("user32.dll", CharSet = CharSet.Auto)]
     internal static extern int GetSystemMetrics(Int32 nIndex);
  }

  private static class Kernel32 {
     [DllImport("kernel32.dll", SetLastError = true)]
     internal static extern Int32 GetCurrentThreadId();
  }

  private static class SystemMetrics {
     internal static Int32 MouseWheelScrollDelta {
        get {
           return 120;
        }
     }

     internal static Int32 MouseWheelScrollLines {
        get {
           var scrollLines = 0;

           if (User32.GetSystemMetrics(75) == 0) {
              var hwnd = User32.FindWindow("MouseZ", "Magellan MSWHEEL");
              if (hwnd != IntPtr.Zero) {
                 var windowMessage = User32.RegisterWindowMessage("MSH_SCROLL_LINES_MSG");
                 scrollLines = (Int32)User32.SendMessage(new HandleRef(null, hwnd), windowMessage, 0, 0);
                 if (scrollLines != 0) {
                    return scrollLines;
                 }
              }
              return 3;
           }
           User32.SystemParametersInfo(104, 0, ref scrollLines, 0);
           return scrollLines;
        }
     }
  }

  private enum WindowsMessage {
     KeyDown = 0x0100,
     KeyUp = 0x0101,
     Char = 0x0102,

     MouseMove = 0x0200,
     LeftButtonDown = 0x0201,
     LeftButtonUp = 0x0202,
     LeftButtonDoubleClick = 0x0203,

     RightButtonDown = 0x0204,
     RightButtonUp = 0x0205,
     RightButtonDoubleClick = 0x0206,

     MiddleButtonDown = 0x0207,
     MiddleButtonUp = 0x0208,
     MiddleButtonDoubleClick = 0x0209,

     MouseWheel = 0x020A,
  }

  private struct Message {
     internal IntPtr HWnd;
     internal Int32 Msg;
     internal IntPtr WParam;
     internal IntPtr LParam;
     internal IntPtr Result;
  }

  private IntPtr hookHandle;
  private ProcessMessagesDelegate processMessages;

  private Int32 ProcessMessages(Int32 code, Int32 wParam, ref Message lParam) {
     if (this.Enabled && code == 0 && wParam == 1) {

        bool processed = false;

        switch ((WindowsMessage)lParam.Msg) {
           case WindowsMessage.KeyDown:
           case WindowsMessage.KeyUp:
           case WindowsMessage.Char:
              WebKeyboardEvent keyboardEvent = new WebKeyboardEvent((uint)lParam.Msg, lParam.WParam, lParam.LParam, 0);

              awesomiumContext.Post(state => {
                 if (!WebView.IsLive) return;
                 WebView.InjectKeyboardEvent(keyboardEvent);
              }, null);

              processed = true;
              break;

           case WindowsMessage.MouseWheel:
              var delta = (((Int32)lParam.WParam) >> 16);
              awesomiumContext.Post(state => {
                 if (!WebView.IsLive) return;
                 WebView.InjectMouseWheel(delta / SystemMetrics.MouseWheelScrollDelta * 16 * SystemMetrics.MouseWheelScrollLines, 0);
              }, null);

              processed = true;
              break;
        }

        if (!processed) {
           WindowsMessage message = (WindowsMessage)lParam.Msg;
           awesomiumContext.Post(state => {
              if (!WebView.IsLive) return;

              switch (message) {
                 case WindowsMessage.MouseMove:
                    var mouse = Mouse.GetState();
                    WebView.InjectMouseMove(mouse.X - area.X, mouse.Y - area.Y);
                    break;

                 case WindowsMessage.LeftButtonDown:
                    WebView.InjectMouseDown(MouseButton.Left);
                    break;
                 case WindowsMessage.LeftButtonUp:
                    WebView.InjectMouseUp(MouseButton.Left);
                    break;
                 case WindowsMessage.LeftButtonDoubleClick:
                    WebView.InjectMouseDown(MouseButton.Left);
                    break;

                 case WindowsMessage.RightButtonDown:
                    WebView.InjectMouseDown(MouseButton.Right);
                    break;
                 case WindowsMessage.RightButtonUp:
                    WebView.InjectMouseUp(MouseButton.Right);
                    break;
                 case WindowsMessage.RightButtonDoubleClick:
                    WebView.InjectMouseDown(MouseButton.Right);
                    break;

                 case WindowsMessage.MiddleButtonDown:
                    WebView.InjectMouseDown(MouseButton.Middle);
                    break;
                 case WindowsMessage.MiddleButtonUp:
                    WebView.InjectMouseUp(MouseButton.Middle);
                    break;
                 case WindowsMessage.MiddleButtonDoubleClick:
                    WebView.InjectMouseDown(MouseButton.Middle);
                    break;
              }
           }, null);
        }
        User32.TranslateMessage(ref lParam);
     }

     return User32.CallNextHookEx(IntPtr.Zero, code, wParam, ref lParam);
  }
}

更新: 请注意,在我的组件中,为了连接消息泵,我使用

int currentThread = Kernel32.GetCurrentThreadId();
// Create the message hook.
hookHandle = User32.SetWindowsHookEx(3, ProcessMessages, IntPtr.Zero, currentThread);

我的界面在 Offscreen webview 中所以比较复杂,这应该也适合你

我发布了一个单独的答案来给出另一个方向: 看看这个要点:https://gist.github.com/robertkhrona/918109

好像建议做

webView.InjectMouseMove(x,y);
webView.InjectMouseDown(MouseButton.Left);
webView.InjectMouseMove(x,y);
webView.InjectMouseUp(MouseButton.Left);

所以在两个mousedown/up事件之间移动(到相同的位置) 顺便说一句,我认为这不需要

你是哪个版本的 awesomium 运行?

更新: 请记住在注入输入之前将焦点设置在 WebView 上

webView.Focus();

我将视图类型设置为屏幕外并且 injectclick 工作正常,当设置为 window 时它不起作用。我不知道为什么,但我可以解决这个问题。

如文档中所述(请参阅:WebViewType),窗口化 视图会捕获所有输入本身,您不能inject 使用 Awesomium API 以编程方式输入(您可以尝试通过将本机 Windows 消息发送到适当的 HWND 来执行此操作,但这不是建议的直接过程) .

为了能够使用 InjectXXX 方法以编程方式注入 输入,请确保您的视图类型为 offscreen.