wpfwinformswinforms-interop

Keyboards inputs in a WPF user control are not sent to the WinForms container


We have a WinForms application that we are progressively converting to WPF. At this point the application's main form is a Form (WinForm) that contains a vertical sidebar built in WPF. The sidebar is hosted in an ElementHost control.

In the main form, KeyPreview is set to true and we override OnKeyDown() to process application wide keyboard shortcuts. When the sidebar has the focus, keyboard events are not sent to OnKeyDown.

What is the correct way to fix this?


Solution

  • Yes, it seems the KeyPreview is not consider by ElementHost, here is a workaround:

    Derive from ElementHost and override ProcessCmdKey, when the base.ProcessCmdKey result says "not processed", pass the message to the parent even if it is not your main form, this way your main form will receive it because other winforms control will behave correctly. Here is a sample...

    public class KeyPreviewEnabledElementHost : ElementHost
    {
        public KeyPreviewEnabledElementHost()
        {
        }
    
        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); 
    
        protected override bool ProcessCmdKey(ref System.Windows.Forms.Message m, System.Windows.Forms.Keys keyData)
        {
            bool processed = base.ProcessCmdKey(ref m, keyData);
    
            if (!processed)
            {
                SendMessage(Parent.Handle, m.Msg, m.WParam, m.LParam);
            }
    
            return processed;
        }
    }