【发布时间】:2011-03-18 02:29:18
【问题描述】:
是否可以在 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 项目,该项目使用将控制台窗口嵌入到 shell 中的 CommandBar 项目来执行此操作:
http://www.codeproject.com/KB/cs/commandbar.aspx
所以我希望它也可以用 WPF 来完成,但我不知道你会怎么做。非常感谢您的帮助(另外,如果您对我在 WPF 中从头开始创建终端窗口的原始问题有任何出色的解决方案,因为这也可以解决我的需求)。
更新:
在 Reed Copsey 的帮助下,我能够嵌入控制台窗口。但是,当然需要对其进行样式设置和移动,否则它看起来就像 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机器。
更新 3: 似乎不支持像这样与其他窗口“混淆”。假设有标题,控制台窗口会计算其文本区域,所以没有办法解决这个问题。我认为在 WPF 中获得类似控制台行为的唯一选择是编写自定义 WinForms 控件,然后将其嵌入 WPF。
【问题讨论】:
-
你成功完成了这件事吗?
-
@ShawnMclean 不......更新代表了整个故事:(
-
您可能会查看 Console2(后来分叉为 ConsoleZ)程序。他们成功地在没有标题/标题的选项卡控件中托管了一系列命令提示符。
-
你是如何将它嵌入到 WPF 中的?接受了 Reed Copsey 的建议并尝试使用 HwndHost,但我失败了。
-
@InfinitiesLoop 嘿,使用 UPDATE 中的代码,我的 cmd 控制台会正确调整大小,但在调用
WIN32API.SetParent(cmdProcess.MainWindowHandle, panel.Handle)然后将面板分配到 WindowsFormsHost.Child = panel` 后,我的控制台不会出现在WindowsFormsHost 的面板。我需要做更多的事情吗?
标签: .net wpf console console-application