在 Windows 窗体中嵌入 DOS 控制台

问题描述 投票:0回答:4

是否可以在 C# 2.0 中的 Windows 窗体或用户控件中嵌入 DOS 控制台?

我们有一个旧版 DOS 产品,我的 Windows 应用程序必须与之交互,并且要求旧版产品的实例应在 Windows 应用程序中运行。

目前,我正在使用 user32.dll 来定位 DOS 产品正在运行的窗口,最小化然后最大化窗口,然后在窗口中输入字符。这并不是一个很好的解决方案,因为这意味着我的应用程序必须将窗口名称存储在应用程序设置中,并且要求用户在使用交互功能之前返回到 DOS 应用程序的正确页面。

编辑:更多信息

旧版应用程序需要对用户可见,但不能在单独的窗口中显示。

我已经尝试过 TimothyP 的答案,它工作得很好,但是是否有可能实现相同的功能,但 DOS 窗口可视化地嵌入到 Windows 窗体或用户控件中,而不是弹出在它自己的窗口中?最好采用 ShowDialog() 方式,这样用户在处于“传统模式”时就无法与应用程序交互。

c# winforms c#-2.0 dos
4个回答
24
投票

可以使用 Process 类重定向控制台/dos 应用程序的标准输入/输出。它可能看起来像这样:

var processStartInfo = new ProcessStartInfo("someoldapp.exe", "-p someparameters");

processStartInfo.UseShellExecute = false;
processStartInfo.ErrorDialog = false;

processStartInfo.RedirectStandardError = true;
processStartInfo.RedirectStandardInput = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.CreateNoWindow = true;

Process process = new Process();
process.StartInfo = processStartInfo;
bool processStarted = process.Start();

StreamWriter inputWriter = process.StandardInput;
StreamReader outputReader = process.StandardOutput;
StreamReader errorReader = process.StandardError;
process.WaitForExit();

您现在可以使用流与应用程序交互。 通过将 processStartInfo.CreateNoWindow 设置为 true,原始应用程序将被隐藏。

我希望这有帮助。


6
投票

关于如何在Windows应用程序中显示DOS应用程序的问题。

有几种解决方案。

  • 第一个是根本不显示DOS应用程序(使用CreateNoWindow) 并通过读取和写入流来“模拟”Windows 应用程序中 DOS 应用程序的 UI。

  • 另一个解决方案是使用 Win32API,获取控制台/DOS 应用程序窗口的 Windows 句柄 (Whnd),并将其父级设置为您的窗体。我目前不在家 由于我已经很久没有这样做了,所以我记不清是怎么做的了。如果我没记错的话,您将需要使用以下 Win32 API 调用:

如果今天晚些时候还有时间,我会看看是否能找到更好的样品。


0
投票

您可以使用 CreateProcess 函数以及 STARTUPINFO 参数的 hStdInput、Output 和 Error 成员,这将允许您拦截应用程序的标准输入和输出。


0
投票

是的,这并不难做到。我刚刚创建了一个用户控件。 我不包括 WindowLongIndex、WindowStyles 和 SetWindowPosFlags 枚举的定义,您可以在互联网上轻松找到它们。

public partial class FormConsole : UserControl
{
    private IntPtr consoleHandle = IntPtr.Zero;

    public FormConsole()
    {
        InitializeComponent();

        Disposed += OnDispose;
    }

    private void OnDispose(object? sender, EventArgs e)
    {
        if (consoleHandle != IntPtr.Zero)
        {
            FreeConsole();
        }
    }

    private void FormConsole_Load(object sender, EventArgs e)
    {
        AllocConsole();
        consoleHandle = GetConsoleWindow();
        SetWindowLong(consoleHandle, WindowLongIndex.GWL_STYLE, WindowStyles.WS_CHILD | WindowStyles.WS_VISIBLE);
        SetParent(consoleHandle, Handle);
        SetWindowPos(consoleHandle, IntPtr.Zero, 0, 0, Width, Height, 0);
        Console.Clear();
    }

    private void FormConsole_Resize(object sender, EventArgs e)
    {
        if (consoleHandle != IntPtr.Zero)
        {
            SetWindowPos(consoleHandle, IntPtr.Zero, 0, 0, Width, Height, 0);
        }
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool AllocConsole();

    [DllImport("kernel32.dll")]
    private static extern IntPtr GetConsoleWindow();

    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, WindowLongIndex index, WindowStyles newLong);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

    [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
    private static extern bool FreeConsole();
}
© www.soinside.com 2019 - 2024. All rights reserved.