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