Можно ли создать консольное окно (созданное AllocConsole) как дочернее окно графического интерфейса?Если так, то как? - PullRequest
0 голосов
/ 21 февраля 2019

Я бы хотел включить функциональность окна консоли в мое приложение WPF для нескольких целей, в том числе:

  • Журнал на экране
  • Отображение результатов команд консоли, выполненных приложением
  • Диагностика

Я использовал два метода:

  • Создайте TextBox и установите его свойство Text с помощью назначения или привязки данных,Это хорошо интегрирует представление в приложение, но имеет проблемы с производительностью, так как текст «буфера» становится большим.
  • Выполните вызов взаимодействия с AllocConsole, чтобы создать окно консоли.Не имеет проблем с производительностью для относительно больших текстовых «буферов», но создается как окно верхнего уровня (визуально отдельно от приложения с собственной строкой заголовка и т. Д.).

В идеале, я 'Я хотел бы создать окно консоли (например, AllocConsole) как дочернее окно моего приложения WPF, аналогично тому, как окно Forms может быть размещено как дочернее окно приложения WPF, чтобы оно могло размещаться на вкладке и т. д..

Насколько я могу судить, невозможно изменить родительский элемент окна после его создания, единственный способ создать новое консольное окно - это AllocConsole, и он не принимает параметров, поэтому родительское окно(например, хост Forms) не может быть указан.Я что-то упустил?

Суть моего вопроса не в том, чтобы аппроксимировать / эмулировать поведение консоли, используя TextBox, ListBox и т. Д., А в том, чтобы разместить фактическое окно консоли в качестве элемента GUI приложения WPF.

РЕДАКТИРОВАТЬ

Где я сейчас нахожусь:

Фрагмент главного окна XAML:

<TabControl>
    <TabItem Header="Log">
        <Grid>
            <WindowsFormsHost x:Name="FormsHost">

            </WindowsFormsHost>
        </Grid>
    </TabItem>
</TabControl>

Код главного окна-behind:

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

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

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

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

    public MainWindow()
    {
        InitializeComponent();

        AllocConsole();

        var newOut = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = true };
        Console.SetOut(newOut);
        Console.SetError(newOut);

        var ptr = GetConsoleWindow();

        FormsHost.Child = new Control();

        SetWindowLong(ptr, -16, GetWindowLong(ptr, -16) | 0x40000000);
        SetParent(ptr, FormsHost.Child.Handle);
        SetWindowPos(ptr, IntPtr.Zero, 0, 0, 300, 300, 0);

        Console.WriteLine("Hello, World");
    }
}

Выше приведено окно консоли на вкладке WPF, но оно по-прежнему выглядит как окно верхнего уровня, и оно по-прежнему может масштабироваться и перемещаться внутри своего хоста.Кроме того, хотя я могу щелкнуть правой кнопкой мыши в области консоли, чтобы получить контекстное меню для выделения текста, я не могу использовать мышь для выделения текста.

UPDATE

Я решил проблему со стилем окна, изменив

SetWindowLong(ptr, -16, GetWindowLong(ptr, -16) | 0x40000000)

на

SetWindowLong(ptr, -16, 0x50000000)

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

1 Ответ

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

Из того, что я понял, ваше намерение только для вывода (а не ввода), тогда что-то простое, например Console.SetOut, отвечает требованиям.

Это перенаправит вывод консоли наTextWriter на ваш выбор.То, что вы можете затем отобразить, как хотите.

Конечно, вы также можете использовать одну из многих библиотек журналов вместо записи в консоль.Или используйте что-то вроде Debug.Write и т.д ...

Но это быстрый и простой способ прочитать что-либо выводимое на консоль и отображать так, как вы хотите.Или, если хотите, перенаправьте в файл.

Что касается производительности, мне нужно увидеть код, который вы используете.Лично я бы использовал ListBox сверх TextBox для больших объемов данных регистрации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...