Использование встроенной экранной клавиатуры Windows в приложении WPF

Мне нужно использовать компонент OnScreenKeyboard, например Native Windows OSK, в моем приложении Wpf. Я могу вызвать пользовательский интерфейс с помощью Process.Start("osk.exe"), но пользовательский интерфейс появляется поверх основного окна пользовательского интерфейса. Я хочу запустить приложение OSK в нижней части моего приложения. Возможно ли это с какими-либо аргументами? -например. process.StartInfo.WindowPosition=xxx — я бы предпочел использовать его, прежде чем создавать свой собственный компонент.


person Kubi    schedule 12.11.2015    source источник
comment
Главное окно osk.exe использует WS_EX_TOPMOST расширенный стиль окна, поэтому оно всегда находится перед всеми другими не самыми верхними окнами. Этого и следовало ожидать, так как пользователю придется взаимодействовать с OSK. Закрытие его другим окном в значительной степени бросает вызов этой цели. Если вам нужно (временно) скрыть OSK, вызовите ShowWindow в окне верхнего уровня. Более навязчивым способом было бы удалить стиль WS_EX_TOPMOST (SetWindowLongPtr).   -  person IInspectable    schedule 12.11.2015


Ответы (1)


OK. Я решил свою проблему с помощью метода Win32 SetWindowPos. Делитесь, если это может помочь другим. Ниже код открывает и изменяет размер/позиционирование Native OSK.exe. Он размещает клавиатуру относительно положения мыши.

[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
    public int X;
    public int Y;

    public static implicit operator Point(POINT point)
    {
        return new Point(point.X, point.Y);
    }
}

    [DllImport("user32.dll")]
    public static extern bool GetCursorPos(out POINT lpPoint);

    public static Point GetCursorPosition()
    {
        POINT lpPoint;
        GetCursorPos(out lpPoint);
        //bool success = User32.GetCursorPos(out lpPoint);
        // if (!success)

        return lpPoint;
    }


    private void OSKMenuItem_Click(object sender, RoutedEventArgs e)
    {
        Process osk = new Process();
        osk.StartInfo.FileName = "osk.exe";
        osk.StartInfo.WindowStyle = ProcessWindowStyle.Normal;

        osk.Start();

        Task.Delay(1000).ContinueWith((a) => {
            Point p = GetCursorPosition();

            try
            {
                IntPtr target_hwnd = FindWindowByCaption(IntPtr.Zero, "On-Screen Keyboard");
                if (target_hwnd == IntPtr.Zero)
                {
                    Microsoft.Windows.Controls.MessageBox.Show("Error");
                }
                SetWindowPos(target_hwnd, IntPtr.Zero, (int)p.X - 200, (int)p.Y, 1300, 600, 0);
            }
            catch (Exception ex)
            {

                //throw;
            }
        });
person Kubi    schedule 13.11.2015
comment
Это очень хрупкий код, к тому же довольно непригодный для использования как есть. Попробуйте продвинуться вперед с помощью Process.WaitForInputIdle() и MainWindowHandle. - person Hans Passant; 13.11.2015
comment
Process.WaitforInputIdle странно не работал. Я не знаю почему. - person Kubi; 13.11.2015