2010-07-19 730 views
7

是否可以在WPF窗口内嵌入控制台窗口?在WPF窗口内嵌入控制台窗口

作为一个小小的背景,起初我试图在WPF中从头开始实现一个控制台窗口,除了一个巨大的问题 - 它的速度非常慢之外,它是成功的。看到这里的问题是:
VT100 Terminal Emulation in Windows WPF or Silverlight

因为这似乎不是一种选择,我不是看在我的WPF应用程序,我已经学会了如何在此描述做托管的实际控制台窗口:

No output to console from a WPF application?

这是伟大的,由最好我想有一个控制台窗口看起来像它是WPF应用程序的其它部分的一部分。我知道使用WinForms应用程序是可能的,因为我已经看到它完成了,包括使用SetParent Win32 API。你可以看到一个例子.NET项目与嵌入一个控制台窗口进入壳体这个命令栏项目做的:

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

所以我希望它可以用WPF做的很好,但我没有想法你会怎么做。非常感谢帮助(另外,如果你有任何明智的解决方案来解决我在WPF中从零开始创建终端窗口的原始问题,因为这也解决了我的需求)。

UPDATE:

的帮助里德·科普塞的帮助下,我能得到嵌入在控制台窗口。然而,当然它需要被设计和移动,否则它看起来像一个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); 

但是有一个大问题。出于某种原因,控制台窗口有一个渲染工件。就好像它不是在左下角和右上角重新绘画一样。工件的宽度与标题栏和厚边框的宽度相似,事实上,如果我将工件大小的厚边框留下,则会出现问题。但重新绘制它不会有帮助,因为它重新出现。我可以,例如,移动窗口关闭屏幕并再次修复它,但它很快就重新出现在自己:

rendering artifact http://img837.imageshack.us/img837/6241/renderissue.png

更新2:即使我没有影响情况将它父进入WindowsFormsHost控件。我需要做的就是启动控制台(使用AllocConsole()),然后使用SetWindowLong删除它的标题栏。这是一台win7机器。

UPDATE 3:它似乎'搞乱'与这样的其他窗口不支持。控制台窗口计算其textarea假设有一个标题,所以没有办法解决这个问题。我认为我唯一的选择在WPF中获得类似控制台的行为将是编写一个自定义的WinForms控件,然后将其嵌入到WPF中。

+0

你做到这一点成功? – 2012-06-24 03:24:01

+0

@ShawnMclean Nope ...更新代表整个故事:( – InfinitiesLoop 2012-06-24 04:22:58

+0

)您可能会看到Console2(后来分为ConsoleZ)程序,它们成功地在标签控件中托管了一系列命令提示符,但没有标题/标题 – 2016-06-14 08:16:35

回答

4

您应该可以使用与通过重置为HwndHost而显示的Windows窗体应用程序相同的技术。您甚至可以调整Windows窗体代码,并直接将其放入WindowsFormsHost控件中。

+0

It cann不是那么容易,可以吗?:)我这样做了: SetParent(ConsoleManager.ConsoleWindowHandle,WindowsFormsHost.Handle); 但是控制台窗口没有显示出来..只要它被重新设置,它就会消失。有任何想法吗? – InfinitiesLoop 2010-07-19 21:47:30

+0

尝试在WindowsFormsHost控件中放置(Windows窗体)面板,并将父窗口设置为面板的句柄(而不是控件本身)。 – 2010-07-19 22:17:07

+0

你知道我认为它正在工作,只是窗口有时在父视图之外。我将需要弄清楚下一步如何将两者的大小绑定在一起并隐藏标题栏等。您帮助了很多,谢谢:) – InfinitiesLoop 2010-07-19 22:20:52

5

除了Reed Copsey关于在WPF应用程序中嵌入控制台窗口的优秀建议之外,另一种易于实现的替代策略是简单地通过Process类发出命令,并将两个流重定向到本地WPF的TextBlocks。下面是截图...

enter image description here

这WPF应用程序(有线为“EXE”文件中的Windows资源管理器上下文菜单)执行程序和管道,结果到相应的窗口。

它旨在帮助当您想要运行控制台实用程序,并且当您单击它时,该实用程序会在控制台窗口中呼啸而过,您永远无法看到发生了什么。它还连接到'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'文件并捕获输出,然后调用View Model。整个编码钻大约需要一个小时左右......在Process类

文档是在这里:http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx