Клавиши Alt и вкладка не работают в Windows Forms, открытых из приложения WPF

У меня есть много старых приложений Windows Forms, которые в конечном итоге будут перенесены в WPF (это большое приложение, поэтому его нельзя сделать за один спринт), и я начал этот процесс с создания главного меню в WPF. Приложения Windows Forms - это отдельные окна, открытые из этого меню.

Приложения Windows Forms открываются и работают без каких-либо проблем, кроме проблем, возникающих у меня с сочетаниями клавиш и клавишами Tab. Клавиша табуляции не перемещает фокус на следующий элемент управления, и клавиша Alt для вызова кнопки &Search больше не работает.

Что я делаю неправильно?

5 ответов

Решение

Наконец мне удалось решить проблему, разместив winform внутри элемента управления WindowsFormsHost внутри формы WPF.

public partial class MyWindow : Window
{
    public MyWindow()
    {
        InitializeComponent();

        Form winform = new Form();
        // to embed a winform using windowsFormsHost, you need to explicitly
        // tell the form it is not the top level control or you will get
        // a runtime error.
        winform.TopLevel = false;

        // hide border because it will already have the WPF window border
        winform.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
        this.windowsFormsHost.Child = winform;
    }

}

Обратите внимание, что вам также может понадобиться подключить событие закрытия winform, если у вас есть кнопка для закрытия формы.

Частичное решение, которое я обнаружил, состоит в том, чтобы вызвать это из вашего конструктора WPF: System.Windows.Forms.Integration.WindowsFormsHost.EnableWindowsFormsInterop(); (Вам нужно ссылаться на dll WindowsFormsIntegration.dll)

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

Видеть это:
http://msdn.microsoft.com/en-us/library/system.windows.forms.integration.windowsformshost.enablewindowsformsinterop(v=vs.100).aspx

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

Проблема в том, что у вас нет цикла сообщений Winforms, качающего сообщения. Application.Run() реализован в вашей программе WPF, а не Winforms. Поэтому любой код в Winforms, который обрабатывает сообщения клавиатуры для реализации сочетаний клавиш, не будет работать.

Для этого нет хорошего решения, это, по сути, проблема "не забеременеть". Этот код в Winforms сильно заблокирован, поскольку он позволяет обход CAS. Единственный обходной путь - это отображение производного класса Form, содержащего элементы управления Winforms, с его методом ShowDialog(). Этот метод прокачивает модальный цикл сообщений, Winforms, достаточно хороший, чтобы оживить код обработки сочетаний клавиш. Перестройте ваш подход, сначала преобразуя главные окна, а затем диалоговые.

Другое решение, которое я нашел для обработки фокуса на клавише Tab - переопределить OnKeyDown следующим образом:

protected override void OnKeyDown(KeyEventArgs e)
{
    if (e.KeyCode == Keys.Tab)
    {
        HandleFocus(this, ActiveControl);
    }
    else
    {
        base.OnKeyDown(e);
    }
}

internal static void HandleFocus(Control parent, Control current)
{
    Keyboard keyboard = new Keyboard();
    // Move to the first control that can receive focus, taking into account
    // the possibility that the user pressed <Shift>+<Tab>, in which case we
    // need to start at the end and work backwards.
    System.Windows.Forms.Control ctl = parent.GetNextControl(current, !keyboard.ShiftKeyDown);
    while (null != ctl)
    {
        if (ctl.Enabled && ctl.CanSelect)
        {
            ctl.Focus();
            break;
        }
        else
        {
            ctl = parent.GetNextControl(ctl, !keyboard.ShiftKeyDown);
        }
    }
}

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

Проверить, если IsTabStop="True" а также TabIndex назначен. За Alt + Key ярлык, попробуйте использовать символ подчеркивания (_) вместо амперсанда (&).

Другие вопросы по тегам