0

I'm still new to C# and WPF, as a learning exercise I'm building a simple wrapper in WPF on a unmanaged win32 C++ application. I currently have the unmanaged application hosted using HWNDHOST in a WPF control and am receiving WM_INPUT messages for mouse input but when it comes to keyboard input I'm only receiving WM_KEYUP/DOWN messages for the keyboard but no WM_INPUT messages.

The hosted application unfortunately makes exclusive use of RawInput and so requires the WM_INPUT messages for the keyboard input system to function.

The C# code for the hosting of the app is below:

class EngineHost : HwndHost
{
    #region Win32
    private const int SWP_NOZORDER = 0x0004;
    private const int SWP_NOACTIVATE = 0x0010;
    private const int GWL_STYLE = -16;
    private const int WS_CAPTION = 0x00C00000;
    private const int WS_THICKFRAME = 0x00040000;
    private const int WS_CHILD = 0x40000000;

    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    [DllImport("user32")]
    private static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent);
    #endregion

    #region Members
    private Process _process;
    #endregion

    #region Implementation
    protected override HandleRef BuildWindowCore(HandleRef hwndParent)
    {
        ProcessStartInfo psi = new ProcessStartInfo("Kruger.exe");
        psi.WindowStyle = ProcessWindowStyle.Minimized;
        _process = Process.Start(psi);
        _process.WaitForInputIdle();

        // The main window handle may be unavailable for a while, just wait for it
        while (_process.MainWindowHandle == IntPtr.Zero)
        {
            Thread.Yield();
        }

        IntPtr engineHandle = _process.MainWindowHandle;

        int style = GetWindowLong(engineHandle, GWL_STYLE);
        style = style & ~((int)WS_CAPTION) & ~((int)WS_THICKFRAME); // Removes Caption bar and the sizing border
        style |= ((int)WS_CHILD); // Must be a child window to be hosted
        SetWindowLong(engineHandle, GWL_STYLE, style);

        SetParent(engineHandle, hwndParent.Handle);
        return new HandleRef(this, engineHandle);
    }

    protected override void DestroyWindowCore(HandleRef hwnd)
    {
        if (_process != null)
        {
            _process.CloseMainWindow();
            _process.WaitForExit(5000);

            if (_process.HasExited == false)
            {
                _process.Kill();
            }

            _process.Close();
            _process.Dispose();
            _process = null;
        }
    }
    #endregion
}

Can anyone tell me why the WM_INPUT keyboard messages are not being generated for the hosted application and how/if I can correct that?

  • Using raw input for the mouse makes somewhat sense. Not for a keyboard. Simplest explanation therefore is that host app only configured raw input for the mouse. And that you are somehow interfering with normal keyboard message dispatching. – Hans Passant Aug 23 '14 at 21:46
  • 1
    Why doesnt raw input for the keyboard make sense? It's a pretty commonly used API in the field I'm in. Here is a good post on the matter ( http://molecularmusings.wordpress.com/2011/09/05/properly-handling-keyboard-input/ ). Though that is off-topic. Back to the issue, I don't think I am interfering with the message dispatching as the higher level keyboard events are being received by the host application as are the mouse input messages. The hosted app when run standalone does receive the correct WM_INPUT messages, it is only when embedded in the C# wrapper that the problem occurs. – Bobby Anguelov Aug 24 '14 at 14:53
  • The **real** problem is reparenting a window, and forcing it into another thread's window hierarchy. Unless both processes are prepared for this, and you absolutely know what you're doing, this will not end well. – IInspectable Aug 25 '14 at 08:36
  • 1
    Why is that a problem, especially given that HWNDHost is intended to do exactly what I'm attempting to do. The **REAL** problem is that I'm getting inconsistent forwarding of WM_INPUT messages. Perhaps WM_INPUT for keyboards is ignored in C#/WPF, if so that's cool and I can work around it but I'd like to know if that is the case or if I have done something wrong or am missing something. – Bobby Anguelov Aug 25 '14 at 13:13

0 Answers0