Сочетания клавиш веб-браузера

У меня есть элемент управления WebBrowser, отображающий некоторый HTML.
Я хочу, чтобы пользователь мог копировать весь документ, но не делать ничего другого.

Я установил для свойств IsWebBrowserContextMenuEnabled и WebBrowserShortcutsEnabled значение false и хочу обрабатывать KeyUp и выполнять некоторый код, когда пользователь нажимает Ctrl+C.

Как мне это сделать?
Элемент управления WebBrowser не поддерживает события клавиатуры.
Я попытался использовать событие формы KeyUp с KeyPreview, но оно вообще не сработало.

EDIT: вот мое решение, вдохновленное ответом Джерба.

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);
    }
}

person SLaks    schedule 30.12.2009    source источник


Ответы (4)


Вы тоже можете попробовать этот метод. Поместите его в основную область формы, и он должен поймать все команды клавиатуры. Я использую его для добавления сочетаний клавиш на динамически создаваемые вкладки.

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;
person Jerb    schedule 30.12.2009
comment
Это почти работает, но я не могу получить сообщение для CTRL+C. Если я нажимаю C, keyData становится C, но если я нажимаю Control, с другой клавишей или без нее, keyData становится LButton | ShiftKey | Control, и невозможно определить, какая другая клавиша была нажата. - person SLaks; 30.12.2009
comment
Последний оператор case case Keys.Control|Keys.N делает именно то, что вы пытаетесь сделать. | используется для захвата нескольких ключей. поэтому случай Keys.Control|Keys.C: должен помочь. - person Jerb; 31.12.2009

Это ошибка в Windows Forms. Его реализация IDocHostUIHandler.TranslateAccelerator на самом деле пытается отправить нажатие клавиши на хост ActiveX, вернув S_OK после проверки WebBrowserShortcutsEnabled и сравнения данных ключа с предопределенными сочетаниями клавиш. к сожалению, при обработке клавиатуры Windows Forms свойство сочетания клавиш проверяется во время ProcessCmdKey, что означает, что IDocHostUIHandler.TranslateAccelerator возвращается немного поздно. Это вызывает что-либо в Shortcut (например, Control+C, Del, Control+N и т. д.) перестает работать, когда для параметра WebBrowserShortcutsEnabled установлено значение false.

Вы можете создать или найти класс оболочки ActiveX веб-браузера (например, csexwb2), который предоставляет другой IDocHostUIHandler. Реализация .TranslateAccelerator для повторной проверки сочетаний клавиш. Элемент управления веб-браузера Windows Forms не позволяет настраивать его реализацию IDocHostUIHandler.

person Community    schedule 30.12.2009

вы можете установить крючок сообщений клавиатуры для управления веб-браузером и отфильтровать сообщения клавиш клавиатуры или выполнить некоторую обработку для них. Пожалуйста, посмотрите, будет ли код ниже работать для вас:

[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());
            //....
        }
...

надеюсь, это поможет, с уважением

person serge_gubenko    schedule 30.12.2009

После долгих исследований мы узнали, что это проблема совместимости браузера.

Мы добавили метатег на 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-коде, вы можете назначить метатег свойству текста документа элемента управления веб-браузера перед переходом по URL-адресу. Ниже приведен образец.

    //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");
person Siva Sankar Gorantla    schedule 05.08.2015