【问题标题】:WebBrowser keyboard shortcuts网络浏览器键盘快捷键
【发布时间】:2010-12-31 03:10:34
【问题描述】:

我有一个显示一些 HTML 的 WebBrowser 控件。
我希望用户能够复制整个文档,但不能做任何其他事情。

我已将IsWebBrowserContextMenuEnabledWebBrowserShortcutsEnabled 属性设置为false,我想处理KeyUp 并在用户按下Ctrl+C 时运行一些代码。

我该怎么做?
WebBrowser 控件不支持键盘事件。
我尝试将表单的KeyUp 事件与KeyPreview 一起使用,但它根本没有触发。

编辑:这是我的解决方案,灵感来自 Jerb 的回答。

class CopyableWebBrowser : WebBrowser {
    public override bool PreProcessMessage(ref Message msg) {
        if (msg.Msg == 0x101    //WM_KEYUP
         && msg.WParam.ToInt32() == (int)Keys.C && ModifierKeys == Keys.Control) {
            DoCopy();
            return true;
        }
        return base.PreProcessMessage(ref msg);
    }
    void DoCopy() {
        Document.ExecCommand("SelectAll", false, null);
        Document.ExecCommand("Copy", false, null);
        Document.ExecCommand("Unselect", false, null);
    }
}

【问题讨论】:

    标签: c# .net winforms keyboard-shortcuts webbrowser-control


    【解决方案1】:

    你也可以试试这个方法。把它放在你的主窗体区域,它应该会捕获所有的键盘命令。我用它来为动态创建的标签添加键盘快捷键。

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
        switch (keyData)
        {
            case Keys.Control|Keys.Tab:
                NextTab();
                return true;
            case Keys.Control|Keys.Shift|Keys.Tab:
                PreviousTab();
                return true;
            case Keys.Control|Keys.N:
                CreateConnection(null);
                return true;
        }
        return false;
    

    【讨论】:

    • 这几乎可以工作,但我无法收到 CTRL+C 的消息。如果我按 C,keyDataC,但如果我按 Control,有或没有其他键,keyDataLButton | ShiftKey | Control,并且无法确定按下了哪个其他键(如果有)。
    • 最后一个case语句“case Keys.Control|Keys.N”正在做你想做的事。该|用于捕获多个键。所以“case Keys.Control|Keys.C:”应该可以解决问题。
    【解决方案2】:

    It is a bug in Windows Forms。它的IDocHostUIHandler.TranslateAccelerator 实现实际上尝试通过在检查 WebBrowserShortcutsEnabled 并将键数据与预定义的快捷方式进行比较后返回 S_OK 来将击键发送到 ActiveX 主机。不幸的是,在 Windows 窗体的键盘处理中,在 ProcessCmdKey 期间检查了快捷键属性,这意味着 IDocHostUIHandler.TranslateAccelerator 返回有点太晚了。当 WebBrowserShortcutsEnabled 设置为 false 时,这会导致 Shortcut 枚举中的任何内容(例如 Control+C、Del、Control+N 等)停止工作。

    您可以创建或查找提供不同 IDocHostUIHandler.TranslateAccelerator 实现以再次检查快捷键的 webbrowser ActiveX 包装类(例如csexwb2)。 Windows 窗体 webbrowser 控件不允许自定义其 IDocHostUIHandler 实现。

    【讨论】:

      【解决方案3】:

      您可以为您的网络浏览器控件设置一个键盘消息挂钩,并过滤掉按键消息或对它们进行一些处理。请查看以下代码是否适合您:

      [DllImport("user32.dll", SetLastError = true)]
      static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, IntPtr windowTitle);
      [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
      public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
      [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
      public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
      [DllImport("kernel32.dll")]
      public static extern int GetCurrentThreadId();
      
      public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
      public const int WH_KEYBOARD = 2;
      public static int hHook = 0;
      
      // keyboard messages handling procedure
      public static int KeyboardHookProcedure(int nCode, IntPtr wParam, IntPtr lParam)
      {
          Keys keyPressed = (Keys)wParam.ToInt32();
          Console.WriteLine(keyPressed);
      
          if (keyPressed.Equals(Keys.Up) || keyPressed.Equals(Keys.Down))
          {
              Console.WriteLine(String.Format("{0} stop", keyPressed));
              return -1;
          }
          return CallNextHookEx(hHook, nCode, wParam, lParam);
      }
      
      // find explorer window
      private IntPtr FindExplorerWindow()
      {
          IntPtr wnd = FindWindowEx(webBrowser1.Handle, IntPtr.Zero, "Shell Embedding", IntPtr.Zero);
          if (wnd != IntPtr.Zero)
          {
              wnd = FindWindowEx(wnd, IntPtr.Zero, "Shell DocObject View", IntPtr.Zero);
              if (wnd != IntPtr.Zero)
                  return FindWindowEx(wnd, IntPtr.Zero, "Internet Explorer_Server", IntPtr.Zero);
          }
          return IntPtr.Zero;
      }
      ...
              // install hook    
              IntPtr wnd = FindExplorerWindow();
              if (wnd != IntPtr.Zero)
              {
                  // you can either subclass explorer window or install a hook
                  // for hooking you don't really need a window handle but can use it
                  // later to filter out messages going to this exact window
                  hHook = SetWindowsHookEx(WH_KEYBOARD, new HookProc(KeyboardHookProcedure),
                      (IntPtr)0, GetCurrentThreadId());
                  //....
              }
      ...
      

      希望这会有所帮助,问候

      【讨论】:

        【解决方案4】:

        查了很多,才知道是浏览器兼容性问题。

        我们在 HTML 页面中添加了元标记,然后快捷方式可以正常工作。下面是示例代码。

         <html>
        <body>
        <Head>
        <meta http-equiv="X-UA-Compatible" content="IE=IE8" />
        </head>
        <form>
        First name:<br>
        <input type="text" name="firstname">
        <br>
        Last name:<br>
        <input type="text" name="lastname">
        </form></body>
        </html>
        

        这个问题有三种不同的解决方案。

        1. 添加元标记使网站浏览器兼容。

        2. 重写“PreocessCmdKey”方法并处理快捷方式。

        3. 通过在 FEATURE_BROWSER_EMULATION 下添加密钥来模拟浏览器。

        如果您不想在 html 代码中设置 meta 标签,您可以在导航 URL 之前将 meta 标签分配给 webbrowser 控件的 Document text 属性。下面是示例。

            //Setting compatible mode of IE.
                            this.m_oWebBrowser.DocumentText = @"<html>
                              <head><meta http-equiv=""X-UA-Compatible"" content=""IE=IE8"" /> </head>
                              <body></body>
                              </html>";
        this.m_oWebBrowser.Navigate("www.google.com");
        

        【讨论】:

          猜你喜欢
          • 2011-04-10
          • 1970-01-01
          • 1970-01-01
          • 2010-12-25
          • 1970-01-01
          • 2010-11-27
          • 2014-06-22
          • 1970-01-01
          相关资源
          最近更新 更多