Клавиши 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)
Я говорю частичное, потому что не все нажатия клавиш работают, как ожидалось. Например, кажется, работает хорошо для простых форм.
Это по замыслу. Сочетания клавиш обрабатываются на уровне цикла сообщений, который обнаруживается до того, как сообщение 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
ярлык, попробуйте использовать символ подчеркивания (_) вместо амперсанда (&).