Можно ли создать консольное окно (созданное AllocConsole) как дочернее окно графического интерфейса? Если так, то как?

2

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

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

Я использовал две техники:

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

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

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

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

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

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

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

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

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

Кодовое окно главного окна:

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, но оно по-прежнему выглядит как окно верхнего уровня, и оно по-прежнему может масштабироваться и перемещаться внутри своего хоста. Кроме того, хотя я могу щелкнуть правой кнопкой мыши в области консоли, чтобы получить контекстное меню для выделения текста, я не могу использовать мышь для выделения текста.

ОБНОВИТЬ

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

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

в

SetWindowLong(ptr, -16, 0x50000000)

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

  • 0
    Возможный дубликат создания .NET TextBox в стиле FIFO
  • 0
    @eocron Я уже давно не использую TextBox и / или другие элементы управления GUI для имитации окна консоли; кажется, что у них всех есть проблемы того или иного рода. Цель этого вопроса - изучить возможность размещения фактического окна консоли в родительском WPF.
Показать ещё 2 комментария
Теги:
wpf
console

1 ответ

2

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

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

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню