Вставить консольное окно в окно WPF - PullRequest
12 голосов
/ 19 июля 2010

Можно ли встроить консольное окно в окно WPF?

В качестве небольшого фона я сначала попытался реализовать консольное окно с нуля в WPF, что оказалось успешным, за исключением одной огромной проблемы.- это очень медленно.См. Вопрос здесь:
эмуляция терминала VT100 в Windows WPF или Silverlight

Так как это не похоже на вариант, я вместо этого смотрю на размещение реального окна консоли в моем WPFприложение, которое я научился делать, как описано здесь:

Нет вывода на консоль из приложения WPF?

И это здорово, но в идеале яМне бы хотелось, чтобы это окно консоли выглядело как часть остальной части приложения WPF.Я знаю, что это возможно с приложением WinForms, как я видел, включая использование SetParent Win32 API.Вы можете увидеть пример проекта .NET, который делает это с этим проектом CommandBar, который встраивает консольное окно в оболочку:

http://www.codeproject.com/KB/cs/commandbar.aspx

Так что я надеюсь, что это можно сделать с WPF какхорошо, но я понятия не имею, как ты это сделаешь.Помощь очень ценится (также, если у вас есть какие-то блестящие решения моей первоначальной проблемы создания окна терминала с нуля в WPF, так как это также решило бы мои потребности).

ОБНОВЛЕНИЕ:

С помощью Рида Копси мне удалось встроить консольное окно.Однако, конечно, его нужно было стилизовать и перемещать, иначе он просто выглядел как обычное консольное окно внутри окна WPF.Мне нужна строка заголовка и большие границы удалены.Проводя исследование, я выяснил, как использовать Win32 API для этого следующим образом:

uint style = GetWindowLong(ConsoleManager.ConsoleWindowHandle, GWL_STYLE);
style &= ~(uint)WindowStyles.WS_CAPTION;
style &= ~(uint)WindowStyles.WS_THICKFRAME;
style &= ~(uint)WindowStyles.WS_DLGFRAME;
style &= ~(uint)WindowStyles.WS_POPUP;
SetWindowLong(ConsoleManager.ConsoleWindowHandle, GWL_STYLE, style);
MoveWindow(ConsoleManager.ConsoleWindowHandle, 0, 0, (int)WindowsFormsHost.ActualWidth, (int)WindowsFormsHost.ActualHeight, true);

Однако есть одна большая проблема.По некоторым причинам в окне консоли есть артефакт рендеринга.Это как если бы оно не перекрашивалось в нижнюю левую и верхнюю правую стороны.Ширина артефакта аналогична ширине строки заголовка и толстой границы, и на самом деле, если я оставлю толстую границу, размер артефакта уменьшится.Но просто перекрасить это не поможет, так как он появляется снова.Я могу, например, переместить окно за пределы экрана и обратно, чтобы исправить его, но вскоре оно снова появляется само по себе:

артефакт рендеринга http://img837.imageshack.us/img837/6241/renderissue.png

ОБНОВЛЕНИЕ 2: Эффект происходит, даже если я не добавляю его в элемент управления WindowsFormsHost.Все, что мне нужно сделать, чтобы воспроизвести его, это запустить консоль (используя AllocConsole ()), а затем удалить ее строку заголовка с помощью SetWindowLong.Это машина win7.

ОБНОВЛЕНИЕ 3: Кажется, что "возиться" с другими окнами, как это не поддерживается.Окно консоли вычисляет свою текстовую область, предполагая, что есть заголовок, поэтому нет никакого способа обойти это.Я думаю, что мой единственный вариант получить консольное поведение в WPF - написать собственный элемент управления WinForms, а затем внедрить его в WPF.

Ответы [ 2 ]

8 голосов
/ 18 октября 2013

В дополнение к превосходному совету Reed Copsey по встраиванию окна консоли в приложение WPF, альтернативной стратегией, которая смехотворно проста в реализации, было бы просто выполнить команду через класс Process и перенаправитьдва потока в родные текстовые блоки WPF.Вот снимок экрана ...

enter image description here

Это приложение WPF (подключенное к контекстному меню Windows Explorer для файлов 'exe') выполняет программу и направляет результаты в соответствующее окно.

Он разработан, чтобы помочь, когда вы хотите запустить консольную утилиту, и когда вы щелкаете по ней, утилита свистит в окне консоли, и вы никогда не увидите, что произошло.Он также подключен к файлам 'csproj' для запуска MSBuild на них из Проводника.

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

Внутренние компоненты этого приложения используют этот класс ...

public class ProcessPiper
{
    public string StdOut { get; private set; }
    public string StdErr { get; private set; }
    public string ExMessage { get; set; }
    public void Start(FileInfo exe, string args, Action<ProcessPiper>onComplete)
    {
        ProcessStartInfo psi = new ProcessStartInfo(exe.FullName, args);
        psi.RedirectStandardError = true;
        psi.RedirectStandardOutput = true;
        psi.UseShellExecute = false;
        psi.WorkingDirectory = Path.GetDirectoryName(exe.FullName);
        Task.Factory.StartNew(() =>
            {
                try
                {
                    ExMessage = string.Empty;
                    Process process = new Process();
                    process.StartInfo = psi;
                    process.Start();
                    process.WaitForExit();
                    StdOut = process.StandardOutput.ReadToEnd();
                    StdErr = process.StandardError.ReadToEnd();
                    onComplete(this);
                }
                catch (Exception ex)
                {
                    ExMessage = ex.Message;
                }
            });
    }
}

Этот класс выполняет именованный файл 'exe' и захватывает выходные данные, а затем вызывает модель представления.Весь процесс кодирования должен занять около часа или около того ...

Документы по классу Process находятся здесь: http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx

7 голосов
/ 20 июля 2010

Вы должны быть в состоянии использовать ту же технику, что и приложение Windows Forms, которое вы показали, перевоплощение в HwndHost . Вы даже можете просто адаптировать код Windows Forms и поместить его непосредственно в WindowsFormsHost control.

...