Accepting Keys in WPF

Oct 16, 2015 at 10:51 PM
I'm not sure if this is a common problem or not, but common WPF controls like TextBox don't accept key strokes. I can copy and paste text in to the TextBoxes, but it won't accept the keyboard events. It's as though Ableton is intercepting the key events and using them solely for emulating the musical keyboard or whatever. Any tricks here? Is there anything I can do? Quite stuck on this.
Oct 25, 2015 at 12:28 AM
Still stuck on this one...
Oct 25, 2015 at 7:48 AM
Kruddler wrote:
I'm not sure if this is a common problem or not, but common WPF controls like TextBox don't accept key strokes. I can copy and paste text in to the TextBoxes, but it won't accept the keyboard events. It's as though Ableton is intercepting the key events and using them solely for emulating the musical keyboard or whatever. Any tricks here? Is there anything I can do? Quite stuck on this.
If you're programming with VST.Core (I haven't used the Framework yet), did you return True in the EditorKeyDown and EditorKeyUp functions? Otherwise, no key input is handled...
Oct 27, 2015 at 10:43 PM
Have you tried intercepting keystrokes on your main container panel? If it works at that level than it could be a keyboard control focus problem within WPF.
Oct 30, 2015 at 10:44 PM
Edited Oct 30, 2015 at 10:45 PM
Thanks for pointing this out Msav and Yury. These methods might help me.

Well, I can confirm that I am able to intercept key strokes in the EditorKeyDown method. It was set to return false, but I set it to return true. Still the result is the same. My WPF controls are not accepting any input.

I'm hoping that I don't have to call SendKeys at the Windows API level or something similar to get this to work...

I don't understand why Ableton is gobbling up the keys and not passing them to WPF. Are you saying that you don't have this problem Yury? Is there something special you've done to route key down events in to your app?
Nov 15, 2015 at 9:07 PM
From Yury:

To put it simply WPF doesn't expose a traditional WIN32 message pump and controls do not exhibit the standard behavior expected from controls that derived from the window class (HWND every control is a Window concept)

How do you think I would get around this?
Nov 16, 2015 at 11:10 PM
Edited Nov 16, 2015 at 11:15 PM
It depends on your implementation. If you could provide a minimal host reproducing the issue that would help greatly. A quick test you can make is to create and show a modal or modeless dialog window in your plugin EditorOpen. Put a control accepting keyboard events in there and see if it works. If that's the case, it probably means there's a problem with the HwndSource interop of the WPF message pump. When you created a WPF window in your plugin the HwndSource is the WPF window instead of the plugin window inside the host and the pump should work correctly. To resolve your issue, you want the plugin window inside the host to be sharing it's message pump with WPF and you'll need to set up explicit keyboard interop between the two message pumps.

My guess is that you're using a HwndHost instead of a WinFormsHost. If that's the case then the following applies. Unlike WinFormsHost, HwndHost doesn't provide implicit keyboard interop. You'll need to specify HwndSource, override (hook) into the Win32 message pump (WndProc), use something like ThreadFilterMessage to intercept the messages, transform the LPARAM and WPARAM of the WIN32 message if needed and use the ComponentDispatcher to send them through the WPF pipeline (SendKeys not need ;)

You should find information on how to do this on the page I linked in the other thread:
https://msdn.microsoft.com/library/aa348549(v=vs.100).aspx

There might be another solution but it is pretty much equivalent to using a HwndHost and bolting on the parts that are in WinFormsHost.
You'd be looking at methods like ElementHost.EnableModelessKeyboardInterop and ComponentDispatcher.RaiseThreadMessage to explicity enable interop on the HwndHost.
Nov 17, 2015 at 12:42 AM
I think you've given me a lot to investigate there! Thankyou very much. If I can't resolve it using this, I'll create a sample and upload it.
Nov 17, 2015 at 12:44 AM
Edited Nov 17, 2015 at 12:45 AM
After thinking a while about it, there is another likely scenario from the page I linked to:
A message that goes to the keyboard sink might not be sent to the HWND if you added hooks for that message by using the AddHook method. The message might have been handled at the message pump level directly and not submitted to the DispatchMessage function.

From your point of view you haven't used keyboard hooks but Vst.Net might have been. In that case you'd still need to hook explicitely the message pump for keyboard events that have been swallowed by a hook in one of your API.
Nov 17, 2015 at 1:08 AM
I think you've given me a lot to investigate there
  • I'd suggest you just go with creating a modeless and a modal dialog with a control that accept keyboard messages and see how it goes. I have no idea of the technical limitation behind. I can only speculate that it has to do with interop performance tradeoff or with event bubbling implementation details that exploit WIN32 behaviors. Having keyboard working in a focused modal WPF window would explain something about the message pump.
Dec 6, 2015 at 2:26 AM
Problem solved!!!

The problem was that the window style was set to WS_CHILD. I don't know why, but this was causing the issue. Once I removed this, the problem went away.

Obiwan, I got this code from WpfControlWrapper in the project Jacobi.Vst.Samples.CorePlugin. I'd suggest that this might be wrong and causing the same issue if other people use this code. I hadn't changed the code, but you can see it here:
        public void Open(IntPtr hWnd)
        {
            _instance = new T();
            _instance.Width = _width;
            _instance.Height = _height;

            HwndSourceParameters hwndParams = new HwndSourceParameters("VST.NET Wpf Editor");
            hwndParams.ParentWindow = hWnd;
            hwndParams.Height = _height;
            hwndParams.Width = _width;
            hwndParams.WindowStyle = 0x10000000|0x40000000; // WS_VISIBLE|WS_CHILD
            
            _hwndSource = new HwndSource(hwndParams);
            _hwndSource.RootVisual = _instance;
        }
I actually removed the Windows Style completely and now there is no issue! Yes! Another hurdle jumped over.
Dec 6, 2015 at 2:28 AM
Ah, but unfortunately, now there is another white window behind the scenes....

I'll have to figure out what to do about that. But, lastly, my window is now properly resizable which is another great win!
Dec 6, 2015 at 2:37 AM
Unfortunately, this is what the extra window looks like now:

Image
Coordinator
Dec 6, 2015 at 5:56 AM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Coordinator
Dec 6, 2015 at 5:58 AM
I have made a note for the WS_CHILD windows style. Thanx!

Could there be a problem in the size of the window for your plugin that you're reporting back? You know, the the rect?
Dec 6, 2015 at 6:04 AM
Do you mean, too big, or too small? Nah. It's the size I want it to be. At least on startup.

The problem is basically that if you set the style to WS_CHILD, the window works properly - i.e. there is no blank second window, but the window doesn't accept key downs. If you don't set the WS_CHILD style, key downs work fine, but you get that blank window sitting behind the editor.