如何使用SendKeyEvent将组合密钥发送到GeckoFX

时间:2016-03-18 15:37:42

标签: c# combinations geckofx

我可以将密钥发送到 GeckoFX扩展浏览器,但现在我想发送组合密钥但代码不能正常工作:

这是我的代码

txtLog.AppendText("Pressing `Ctrl+Enter`...\n");
webBrowser1.Window.DomWindow.Focus();
webBrowser1.Window.WindowUtils.SendKeyEvent("keydown", 17, 0, 0, true);
webBrowser1.Window.WindowUtils.SendKeyEvent("keydown", 13, 0, 0, true);
webBrowser1.Window.WindowUtils.SendKeyEvent("keypress", 13, 0, 0, true);
webBrowser1.Window.WindowUtils.SendKeyEvent("keyup", 13, 0, 0, true);
webBrowser1.Window.WindowUtils.SendKeyEvent("keyup", 17, 0, 0, false);

它不会随时按Ctrl + Enter键。

如何让它发挥作用?

2 个答案:

答案 0 :(得分:0)

我从未使用geckofx WindowUtils,但如果它在Windows窗体应用程序中,您可以使用System.Windows.Forms.SendKeys类向元素发送击键。您也可以添加组合键。我不确定语法,但可能SendKeys.Send("^({ENTER})")。参见

https://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys%28v=vs.100%29.aspx

您可能必须先关注浏览器 - geckoWebBrowser1.Focus();

答案 1 :(得分:0)

我知道这是一个古老的问题,但这不是GeckoFX论坛或位存储桶项目中的问题第一次被问到,而且因为我只是必须从头开始在互联网上找到该信息,我想我会在这里为那些正在寻找它的人回答,因为此SO帖子实际上在该主题的所有相关搜索中都排在首位。

在问题跟踪器,GFX项目或我所看到的其他任何地方,似乎没有人回答或维护这些查询。

在最新版本的GeckoFX60中,旧的“ SendKeyEvent”界面(如OP的原始问题中所使用)已被弃用,不仅将其标记为已弃用,而且如果尝试使用它,则会出现异常告诉您使用“ nsITextInputProcessorCallback ”界面。

该接口未在示例中,或在项目WiKi或任何地方进行记录,仅存在一些深层的问题,这些问题在“ Mozilla IDL”的项目源代码中提供了有关其用法和C#定义的提示。接口”。

由于我有一个较旧的应用程序要升级,所以我必须自己解决问题,我有一个替换的SendKeyEvent调用,其工作方式如下:

private void SendKeyEvent(int keyCode, bool alt, bool ctrl, bool shift)
{
  var instance = Xpcom.CreateInstance<nsITextInputProcessor>("@mozilla.org/text-input-processor;1");
  using (var context = new AutoJSContext(_browser.Window))
  {
    var trans = instance.BeginInputTransaction((mozIDOMWindow)_browser.Document.DefaultView.DomWindow, new TextInputProcessorCallback());

    var keyEvent = context.EvaluateScript(
        $@"new KeyboardEvent('',
               {{ key: '', 
                  code: '',
                  keyCode: {keyCode},
                  ctrlKey : {(ctrl ? "true" : "false")},
                  shiftKey : {(shift ? "true" : "false")},
                  altKey : {(alt ? "true" : "false")} }});");

    var kd = instance.Keydown((nsIDOMEvent)keyEvent.ToObject(), 0, 1);
    var ku = instance.Keyup((nsIDOMEvent)keyEvent.ToObject(), 0, 1);
  }

  Marshal.ReleaseComObject(instance);
}

要进行此项工作,还必须如下定义一个类

  public class TextInputProcessorCallback : nsITextInputProcessorCallback
  {
    //NOTE: This never actually gets called by the input processor shite for doing a simple key press in SendKeyEvent above
    //but the nsi processor crashes if you don't create and specify the damn thing!!!!  basically, DO NOT REMOVE IT
    public bool OnNotify(nsITextInputProcessor aTextInputProcessor, nsITextInputProcessorNotification aNotification)
    {
      Console.WriteLine("TestCallback:OnNotify");
      return true;
    }
  }

作为我在类状态下的注释,它似乎永远不会被GeckoFX调用或以任何有意义的方式使用,但是,如果您不将其包含在代码中,请在密钥的BeginTransaction调用中使用它按下Mozilla NSI处理器xpcom内核会崩溃和/或变色并导致问题。

要使用它,很简单,keyCode是浏览器的VK_xxxx代码,因此例如,如果要将“ 1”键发送给具有

的浏览器,
VK_1 (49)

所以

SendKeyEvent(49, false, false, false)

将导致浏览器看到该按键

注意::新方法仅会生成KeyDown和KeyUp,而不是KeyPress,但是,如果您在DOM键事件类的MDN上阅读了说明,就会看到KeyPress正在已弃用并逐步淘汰。

如果页面中的“ WebCode”仅钩住了javascript中的“ KeyPress”事件,请注意,您的网页将不会选择较新的密钥发送方法,因此您需要调整页面代码查找KeyUp / KeyDown事件。

出于完整性考虑,旧方法(具有兼容的方法签名)已在我的代码中定义如下:

private void SendKeyEvent(int keyCode, bool alt, bool ctrl, bool shift)
{
  //TODO: combine modifiers
  var modifiers = 0;
  _browser.Window.WindowUtils.SendKeyEvent("keydown", keyCode, 0, modifiers, true);
  _browser.Window.WindowUtils.SendKeyEvent("keypress", keyCode, 0, modifiers, true);
  _browser.Window.WindowUtils.SendKeyEvent("keyup", keyCode, 0, modifiers, true);
}

我仍然需要计算修饰符的标志值/顺序,它会在MDN上的某个地方,但是我现在不需要它,所以我有空的时候会去查找它。

这在我使用的WindowsForms代码中对我有用,请当心它对线程敏感,如果您对事件的响应与持有GeckoFX浏览器控件的UI不在同一线程上,您将得到一个调用时出现异常,但是正确放置Invoke检查并调用将解决该问题。