【问题标题】:Redirecting console output to MFC screen output within the same solution在同一解决方案中将控制台输出重定向到 MFC 屏幕输出
【发布时间】:2013-11-25 22:32:40
【问题描述】:

我整天都在搞砸,试图让我的 MFC 应用程序在屏幕上显示控制台应用程序的日志输出。从 Visual Studio 2013 的向导给我的开始,我能够修改他们的代码以将字符串作为输入并制作应用程序消息的运行日志(如下):

void COutputWnd::FillBuildWindow(std::string build_text)
{
std::wstring wsTmp(build_text.begin(), build_text.end());
std::wstring z = wsTmp;
LPTSTR x = new TCHAR[z.size() + 1];
_tcscpy(x, z.c_str());
m_wndOutputBuild.AddString(x);
free(x);
}

但是,由于多种原因,我不能从 MFC 函数外部调用它。一是该对象在全局范围内不可见,二是我在我的应用程序的控制台部分使用 windows.h,它不能很好地与 MFC 配合使用。

我的大部分应用程序已经编写完毕,我正在尝试在它周围放置一个 GUI 并使用功能区功能。有没有办法获取 cout 语句并将它们通过管道传输到我的 MFC 应用程序中的消息日志显示?我今天搜索了很多东西,但没有找到任何直接或明确的应用程序,这些应用程序将 MFC 和控制台代码作为其解决方案的一部分。我没有调用单独的可执行文件或 dll。这全部编译为一个独立的 exe。

【问题讨论】:

  • 您是否尝试写入 VS 中的“调试输出”窗口?
  • 不,我正在尝试向用户展示输出。例如,他们有一个高尔夫分数列表,我在输出屏幕中给他们排名靠前的球员。或者错误,比如他们有错误的数据。
  • 考虑到 MFC 的 <afxv_w32.h> 包含 <windows.h>,声称 MFC 不能很好地处理 <windows.h> 有点牵强。

标签: c++ visual-c++ mfc


【解决方案1】:

我不知道 MFC,但我会从 std::streambuf 派生一个类,以将其输出重定向到 MFC 类并将生成的流缓冲区安装到 std::cout。流缓冲区处理写入流的输出,您可以在其overflow()sync() 方法中获取写入的字符:

class windowbuf
    : std::streambuf {
    SomeHandle handle;
    char       buffer[256];
public:
    typedef std::char_traits<char> traits;
    windowbuf(SomeHandle handle): handle(handle) { this->setp(buffer, buffer + 255); }
    int overflow(int c) {
        if (!traits::eq_int_type(c, traits::eof())) {
            *this->pptr() = traits::to_char_type(c);
            this->pbump(1);
        }
        return this->sync() == -1? traits::eof(): traits::not_eof(c);
    }
    int sync() {
        writeToHandle(this->handle, this->pbase(), this->pptr() - this->pbase());
        this->setp(buffer, buffer + 255);
        return 0;
    }
};

上面是一个简单的流缓冲区,当缓冲区已满或流被刷新时,它会在handle 标识的某个位置传输字符。我认为提出一些句柄和一个将字符传输到 MFC 窗口的写入函数应该是可行的,尽管我对此部分一无所知。

要让std::cout 将其字符发送到上面的流缓冲区,您只需要将这个流缓冲区安装到std::cout,例如,使用

int main() {
    SomeHandle handle = get_a_handle_from_somewhere();
    std::streambuf* cout_rdbuf = std::cout.rdbuf(new windowbuf(handle));
    // run your program here
    std::cout.rdbuf(cout_rdbuf); // this should really be restored using RAII approaches
}

我认为类似上述方法的方法应该能够弥合写入std::cout 的某些代码与使用某种 GUI 显示信息的代码的其他部分之间的差距。

【讨论】:

  • 您遗漏了最困难的部分:附加到控制台的 STDOUT,get_handle_from_somewhere() 后面的部分。如果你使这个非阻塞(你必须这样做,因为你在 GUI 线程上运行),额外的积分。
  • @IInspectable:我当然没有遗漏捕获程序输出到std::cout 的部分:这就是流缓冲区的全部内容!最初的请求实际上不是关于捕获程序输出,而是写入到std::cout 的内容要容易得多。在线程之间传输字符也不是什么大问题:只需将它们写入合适的队列即可。
  • 我明白你的意思,你的 SomeHandle 指的是 GUI 小部件。在线程之间传输输出仍然有些涉及。不过,我要 +1。
  • 我希望它不会被卷入其中。有人会认为微软有一个更简单的解决方案,可以将一个 hpp 文件的输出写入另一个 hpp 文件的窗口。
  • @matusi143:我无法评论 Windows 部分,我可以想象有一个类大致完成了我上面概述的操作。但是,我是一名 UNIX 程序员,我只能评论它的 IOStreams 方面。上述方法仍然可以为找到合适的课程提供必要的起点。
猜你喜欢
  • 2013-11-14
  • 1970-01-01
  • 2019-02-13
  • 2021-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
相关资源
最近更新 更多