Alt keys and tab don't work in Windows Forms opened from a WPF application
Asked Answered
T

5

10

I have lots of old Windows Forms applications that will eventually be ported to WPF (it is a large application so it can't be done in one sprint), and I have started the process by creating a main menu in WPF. The Windows Forms applications are separate windows opened from this menu.

The Windows Forms applications are opening and working without any problems except the issues I am having with the shortcut and Tab keys. The tab key is not moving focus to the next control, and the Alt key to trigger the &Search button no longer works.

What am I doing wrong?

Trimurti answered 31/1, 2012 at 17:11 Comment(0)
T
4

I finally managed to fix the issue by hosting the winform inside a WindowsFormsHost control inside a WPF form.

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

}

Please note that you may also need to hook up the winform close event if you have a button to close the form.

Trimurti answered 1/2, 2012 at 12:51 Comment(0)
U
8

A partial solution I discovered is to call this from your WPF constructor: System.Windows.Forms.Integration.WindowsFormsHost.EnableWindowsFormsInterop(); (You need to reference the dll WindowsFormsIntegration.dll)

I say partial because not all key strokes function as expected. Eg, seems to work okay for simple forms.

See this:
http://msdn.microsoft.com/en-us/library/system.windows.forms.integration.windowsformshost.enablewindowsformsinterop(v=vs.100).aspx

Unstriped answered 11/9, 2013 at 15:25 Comment(1)
That's interesting, I wasn't aware you could do it that way. Thanks!Trimurti
T
4

I finally managed to fix the issue by hosting the winform inside a WindowsFormsHost control inside a WPF form.

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

}

Please note that you may also need to hook up the winform close event if you have a button to close the form.

Trimurti answered 1/2, 2012 at 12:51 Comment(0)
K
3

This is by design. Shortcut keys are handled at the message loop level, detected before the Windows message gets dispatched to the window with the focus. That's the reason those keys can work regardless of the focus.

Problem is, you don't have the Winforms message loop pumping the messages. Application.Run() is implemented by WPF in your program, not Winforms. So any of the code in Winforms that processes keyboard messages to implement shortcut keystrokes won't run.

There's no good solution for this, it is pretty fundamentally the "can't get a little pregnant" problem. This code in Winforms is locked up heavily since it would allow CAS bypass. The only workaround is to display a Form derived class that contain Winforms controls with its ShowDialog() method. That method pumps a modal message loop, the Winforms one, good enough to revive the shortcut keystroke handling code. Restructure your approach by converting the main windows first, dialogs last.

Kentkenta answered 1/2, 2012 at 13:9 Comment(2)
Thanks for the detailed answer. The WindowsFormsHost seems to be the only thing that facilitates passing shortcut keys. It is designed for controls though, not 'top level' forms (so some hacking is required).Trimurti
The usage of ShowDialog() solves the tabbing problem and was very helpful for me! I hope other programmers will find this solution here (was hard for me to find)Foreman
F
2

Another solution I found to handle focus on the Tab key is to override OnKeyDown like this:

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

The advantage of this solution is that it doesn't require neither a WindowsFormsHost nor a message pump which can be a hassle to implement. But I don't know if it is possible to handle shortcuts keys like this because I didn't need it.

Friedrick answered 28/1, 2016 at 14:24 Comment(1)
That's an interesting approach, could be a good alternative for someone :)Trimurti
B
1

Check if IsTabStop="True" and TabIndex is assigned. For Alt + Key shortcut, try using the underscore (_) character instead of the ampersand (&).

Beka answered 31/1, 2012 at 17:16 Comment(2)
Yes, isTabStop="true" for all the relevant controls. The functionality works perfectly when I open the form from a winforms menu, it only breaks when I open the exact same form from a WPF menu. I'm not sure what you mean by using underscore. Ampersand before a letter in the button text will of course be displayed as an underscore when the control is rendered :)Trimurti
@Trimurti I assumed you were converting all your winforms to WPF. Good luck with your conversion!Beka

© 2022 - 2024 — McMap. All rights reserved.