Как встроить tabtip.exe в окна

Я пытаюсь встроить osk в окно wpf или пользовательский элемент управления, и я нашел приведенный ниже код, и он работает для блокнота, но для tabtip.exe он говорит, что у него нет графического интерфейса??

Ошибка функции WaitForInputIdle. Это может быть связано с тем, что у процесса нет графического интерфейса.

Я попытался позволить ему спать некоторое время вместо вызова метода waitForInputIdle, но он выдает другое исключение:

Процесс завершен, поэтому запрошенная информация недоступна.

Но в моем диспетчере задач я все еще вижу запущенный TabTip.exe.

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private System.Windows.Forms.Panel _panel;
        private Process _process;

        public MainWindow()
        {
            InitializeComponent();
            _panel = new System.Windows.Forms.Panel();
            windowsFormsHost1.Child = _panel;
        }

        [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);

        [DllImport("user32")]
        private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);

        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;


        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            base.OnClosing(e);
            if (_process != null)
            {
                _process.Refresh();
                _process.Close();
            }
        }

        private void ResizeEmbeddedApp()
        {
            if (_process == null)
                return;

            SetWindowPos(_process.MainWindowHandle, IntPtr.Zero, 0, 0, (int)_panel.ClientSize.Width, (int)_panel.ClientSize.Height, SWP_NOZORDER | SWP_NOACTIVATE);
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            Size size = base.MeasureOverride(availableSize);
            ResizeEmbeddedApp();
            return size;
        }

        private void button1_Click_1(object sender, RoutedEventArgs e)
        {
            button1.Visibility = Visibility.Hidden;
            ProcessStartInfo psi = new ProcessStartInfo("C:\\Program Files\\Common Files\\microsoft shared\\ink\\TabTip.exe");
            _process = Process.Start(psi);

            Thread.Sleep(500);
            //_process.WaitForInputIdle();

            SetParent(_process.MainWindowHandle, _panel.Handle);

            // remove control box
            int style = GetWindowLong(_process.MainWindowHandle, GWL_STYLE);
            style = style & ~WS_CAPTION & ~WS_THICKFRAME;
            SetWindowLong(_process.MainWindowHandle, GWL_STYLE, style);

            // resize embedded application & refresh
            ResizeEmbeddedApp();
        }

    }
}

Редактировать: Вдохновленный комментарием Рене, я попытался получить ptr окна, как показано ниже, и использовал spy++, чтобы убедиться, что адрес, который дает FindWindow, указывает на правильное окно, но он все еще не движется:

 IntPtr KeyboardWnd = FindWindow("IPTip_Main_Window", null);


 int style = GetWindowLong(KeyboardWnd, GWL_STYLE);
 style = style & ~WS_CAPTION & ~WS_THICKFRAME;
 SetWindowLong(KeyboardWnd, GWL_STYLE, style);
 SetWindowPos(KeyboardWnd, IntPtr.Zero, 0, 0, (int)_panel.ClientSize.Width, (int)_panel.ClientSize.Height, SWP_NOZORDER | SWP_NOACTIVATE);

Редактировать 2: Моя первая мысль заключалась в том, что размер подсказки вкладки нельзя изменить, но затем я заметил поведение, когда я пытаюсь переместить окно на два разных экрана, оно изменит размер, чтобы соответствовать размеру экрана, поэтому я уверен, что там должен быть способ изменить размер, поэтому я запустил spy++(x64) для проверки:

журнал окна

Редактировать 3: после того, как я немного поработал с API-интерфейсом user32 и без прогресса, я попытался использовать сканер памяти для сканирования позиции x и y вкладки и изменить ее, однако он не обновляется до тех пор, пока не будет запущена перерисовка, я задаюсь вопросом о возможности идти по этому пути.


person Mc Kevin    schedule 11.08.2016    source источник
comment
Я предполагаю, что экземпляр, который вы запускаете, немедленно закрывается. Эти ответы предполагают, что вам нужно искать окно, которое не обязательно является главным окном запущенного вами экземпляра процесса.   -  person rene    schedule 11.08.2016
comment
может это поможет вам geekswithblogs.net/TechTwaddle/archive/2009/10/16/   -  person Mangrio    schedule 16.08.2016
comment
@QadeerMangrio Я хочу графически встроить вкладку в другое окно, насколько я понимаю, в блоге говорится о том, как встроить с точки зрения памяти.   -  person Mc Kevin    schedule 19.08.2016


Ответы (1)


Можете ли вы попробовать запустить код дескриптора в потоке STA? У меня была аналогичная проблема с собственным окном, которую я решил с помощью потока STA.

var thread = new Thread(() => {
          // Your code here
});
thread.TrySetApartmentState(ApartmentState.STA);
thread.Start();
person Ankit Vijay    schedule 16.08.2016
comment
Я не уверен, как это будет иметь значение, но я все равно пробовал, это не помогло. - person Mc Kevin; 16.08.2016