Почему я не могу взаимодействовать с окном консоли после добавления его в мое приложение WPF? - PullRequest
0 голосов
/ 22 февраля 2019

Относительно моего предыдущего вопроса :

Я предложил следующий подход, в котором я создал этот элемент управления WinForms:

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public class ConsoleWindow : Control
{
    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool AllocConsole();

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool FreeConsole();

    [DllImport("kernel32.dll")]
    static extern IntPtr GetConsoleWindow();

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    [DllImport("user32.dll", SetLastError = true)]
    static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

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

    private static ConsoleWindow _theWindow;

    public ConsoleWindow()
    {
        if (!DesignMode)
        {
            if (_theWindow != null)
            {
                throw new Exception("An application can have only one ConsoleWindow");
            }
            _theWindow = this;
            AllocConsole();
            var newOut = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = true };
            Console.SetOut(newOut);
            Console.SetError(newOut);

            var consoleHwnd = GetConsoleWindow();

            SizeChanged += (sender, args) =>
            {
                SetWindowPos(consoleHwnd, IntPtr.Zero, 0, 0, Width, Height, 0);
            };

            SetWindowLong(consoleHwnd, -16 /*GWL_STYLE*/, 0x50000000 /* WS_CHILD|WS_VISIBLE*/);
            SetParent(consoleHwnd, Handle);
            SetWindowPos(consoleHwnd, IntPtr.Zero, 0, 0, 0, 0, 0);
        }
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && _theWindow != null)
        {
            FreeConsole();
            _theWindow = null;
        }

        base.Dispose(disposing);
    }
}

... которыйЗатем я могу использовать в своем приложении WPF через XAML, например:

    <WindowsFormsHost>
        <WindowsFormsHost.Child>
            <controls:ConsoleWindow></controls:ConsoleWindow>
        </WindowsFormsHost.Child>
    </WindowsFormsHost>

Это в основном работает, за исключением того, что взаимодействие с мышью кажется нарушенным.Когда вы создаете консольное окно (обычно оно работает как окно верхнего уровня), вы можете использовать мышь, чтобы щелкнуть / перетащить произвольное выделение, но это больше не работает после того, как я стал родительским элементом управления, как я это сделал.Я могу щелкнуть правой кнопкой мыши, чтобы вызвать контекстное меню окна консоли, чтобы выделить / скопировать весь текст, но я не могу сделать выбор щелчком / перетаскиванием.

Есть ли способ исправить это (пропущенные / неправильные стили иливозможно маршрутизация сообщений?), чтобы я мог взаимодействовать с окном консоли, как ожидается, или есть фундаментальная проблема с родительским окном консоли таким образом?

1 Ответ

0 голосов
/ 27 февраля 2019

Существует элемент управления, написанный Дейвом Керром, который решает вашу проблему.

Используйте эту ссылку: https://www.codeproject.com/articles/335909/embedding-a-console-in-a-c-application

, следует добавить, что он использует класс с именем ProcessInterface, который включен вссылка.

и, наконец, эта часть кода является решением:

/// <summary>
        /// Handles the KeyDown event of the richTextBoxConsole control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.KeyEventArgs"/> instance containing the event data.</param>
        void richTextBoxConsole_KeyDown(object sender, KeyEventArgs e)
        {
            bool inReadOnlyZone = richTextBoxConsole.Selection.Start.CompareTo(inputStart) < 0;

            //  If we're at the input point and it's backspace, bail.
            if (inReadOnlyZone && e.Key == Key.Back)
                e.Handled = true;;

            //  Are we in the read-only zone?
            if (inReadOnlyZone)
            {
                //  Allow arrows and Ctrl-C.
                if (!(e.Key == Key.Left ||
                    e.Key == Key.Right ||
                    e.Key == Key.Up ||
                    e.Key == Key.Down ||
                    (e.Key == Key.C && Keyboard.Modifiers.HasFlag(ModifierKeys.Control))))
                {
                    e.Handled = true;
                }
            }

            //  Is it the return key?
            if (e.Key == Key.Return)
            {
                //  Get the input.
                //todostring input = richTextBoxConsole.Text.Substring(inputStart, (richTextBoxConsole.SelectionStart) - inputStart);

                //  Write the input (without echoing).
                //todoWriteInput(input, Colors.White, false);
            }
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...