2

I have Windows Forms windows with tab control and one of its tab hosts ElementHost with ContentControl as child element. This control has collection of input bindings which work only when any child element has input focus but if focus is lost they no longer react. Is it possible to define these input bindings on a higher level in such situation?

Demarsch
  • 1,419
  • 19
  • 39
  • Could you post some code to make it more concrete? What do your bindings look like and what is your proposal for placing them on a higher level (of which I think will not be a good solution) – Youp Bernoulli Sep 07 '14 at 09:59
  • Binding are quite simple, somehting like – Demarsch Sep 07 '14 at 13:27
  • And if windows forms content somehow get focus those key bindings are no longer can be activated. In WPF you can put your bindings into Window element and everything will work – Demarsch Sep 07 '14 at 13:29
  • Tommorow I will have a look in code I have on my external drive at home. I had a similiar problem with a WPF Page in a WinForms Elementhost. Be patient ;) – Youp Bernoulli Sep 07 '14 at 19:23
  • I set up the same situation and can reproduce the "bug". Did some googling and read several posts here and there but no succes so far :( Maybe I will have a closer look later on... – Youp Bernoulli Sep 08 '14 at 13:39

1 Answers1

3

One solution might be to pass (tunnel) keyboard and/or mouse events from Win Forms to WPF host. I made the following proof of concept. It works but has limitations and requires more work. Firstly you will need a class derived from ElementHost. You should use it in your application instead of the standard ElementHost. This new custom class will have only one additional method ProcessWinFormsKeys which will map WinForms specific keys to those used by WPF. Then it will find a proper input binding and execute it.

    public class CustomElementHost : ElementHost
    {
        public void ProcessWinFormsKeys(Keys keys, Keys modifiers)
        {
            var key = KeyInterop.KeyFromVirtualKey((int)keys);

            var modifier = System.Windows.Input.ModifierKeys.None;

            if ((modifiers & Keys.Control) != 0)
                modifier |= System.Windows.Input.ModifierKeys.Control;

            if ((modifiers & Keys.Shift) != 0)
                modifier |= System.Windows.Input.ModifierKeys.Shift;

            if ((modifiers & Keys.Alt) != 0)
                modifier |= System.Windows.Input.ModifierKeys.Alt;

            foreach (InputBinding inputBinding in Child.InputBindings)
            {
                var keyGesture = inputBinding.Gesture as KeyGesture;

                if (keyGesture == null) 
                    continue;

                if(keyGesture.Key == key && keyGesture.Modifiers == modifier)
                    if(inputBinding.Command.CanExecute(inputBinding.CommandParameter))
                        inputBinding.Command.Execute(inputBinding.CommandParameter);
            }
        }
    }

Then in your Form that contains an instance of CustomElementHost you should subscribe KeyDown event and call ProcessWinFormsKeys method within a handler:

    public Form()
    {
        InitializeComponent();

        KeyPreview = true;
        KeyDown += Form_KeyDown;
        ...
    }

    void Form_KeyDown(object sender, KeyEventArgs e)
    {
       elementHost.ProcessWinFormsKeys(e.KeyCode, e.Modifiers);
    }

Another solution might be to utilize global hot keys. It will require to use RegisterHotKey function from user32.dll. However, I'm not sure if it will work with ElementHost. If you want to try there are a few questions on stackoverflow and dozens of article in Internet.

Michał Komorowski
  • 6,198
  • 1
  • 20
  • 24