c++ - 将标准输出重定向到编辑控件 (Win32)。马克二世

标签 c++ winapi redirect

我已经看到一个完全像这样的问题已经存在:Redirect stdout to an edit control (Win32)

但是,给出的解决方案要求程序员实现一个my_printf 函数来执行{printf;从管道读取到编辑控件}。我不能那样做,因为我的 printf 在外部库中。

理想情况下,我在想:

  1. 将应用程序的标准输出重定向到编辑控件
  2. 运行应用程序,瞧

但是如果编辑控件的 API 只允许你向它写入一个字符串,我会想到这样的事情:

1 - 将标准输出复制到管道输出描述符
3 - 从描述符中的管道读入缓冲区
4 - 从缓冲区写入编辑控件

但是,那里缺少第 2 步:

2 - 收到一个信号,表明何时完成对该管道输出描述符的写入。

我怎样才能使那部分自动化。我可以在这里使用套接字 select 之类的东西吗?

[编辑]

所以,根据 David Heffernan 的评论,我会有这样的东西:

  #define MYPRINT      1
  #define WM_MYMESSAGE (WM_USER+1)

  INT_PTR CALLBACK Foo::DialogProc(
    ...
    case WM_COPYDATA:
      {
        PCOPYDATASTRUCT pMyCDS = (PCOPYDATASTRUCT) lParam;
        LPCSTR szString = (LPCSTR)(pMyCDS->lpData);
        AppendLog(szString);
      }
      break;
    ...
  }

  /* static */
  void Foo::MainThread()
  {
    // Create worker thread
    DWORD dwThreadId = 0;
    m_hRedirectStdoutThread = CreateThread(
      // default security
      NULL,
      // default stack size
      0,
      // routine to execute
      (LPTHREAD_START_ROUTINE) &CTracesConsole::RedirectStdoutThreadRun,
      // thread parameter
      NULL,
      // immediately run the thread
      0,
      // thread Id
      &dwThreadId);
    if (NULL == m_hRedirectStdoutThread)
    {
      printf("Error creating stdin thread\n");
      return;
    }

    // Loop forever
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }

  /* static */
  void Foo::RedirectStdoutThreadRun()
  {
    // Redirect stdout to pipe
    int fds[2];
    _pipe(fds, 1024, O_TEXT);
    _dup2(fds[1], 1); // 1 is stdout

    char buffer[1024];
    for (;;)
    {
      // Need to flush the pipe
      _flushall();
      // Read stdout from pipe
      DWORD dwNumberOfBytesRead = 0;
      dwNumberOfBytesRead = _read(fds[0], buffer, 1024 - 1);
      buffer[dwNumberOfBytesRead] = 0;

      // Send data as a message
      COPYDATASTRUCT myCDS;
      myCDS.dwData = MYPRINT;
      myCDS.cbData = dwNumberOfBytesRead + 1;
      myCDS.lpData = buffer;
      PostMessage(g_hWindow,
                  WM_MYMESSAGE,
                  0,
                  (LPARAM)(LPVOID) &myCDS);
    }
  }

AppendLog 将字符串写入编辑控件的位置。

[编辑]

这段代码现在可以正常工作了。有点不便的是,当我从 libcurl 重定向 stdout 跟踪时,libcurl 停止工作 :) 但那是另一个故事......

最佳答案

Windows 支持异步 I/O。这很容易:

  1. 将标准输出复制到管道输出描述符
  2. 发出异步从描述符中的管道读取到缓冲区
  3. 等待消息或事件 (MsgWaitForMultipleObjects)。
    • 如果等待以一条或多条消息结束,调用 PeekMessage(PM_REMOVE) 将它们删除。
    • 如果发出管道事件信号,则将文本从缓冲区复制到编辑控件。

关于c++ - 将标准输出重定向到编辑控件 (Win32)。马克二世,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6532064/

相关文章:

c++ - 如何检查 C++ 类构造函数中的参数大小

c++ - GLUT 显示空白窗口

c# - 双击进度条后打开的窗口立即拖入后台

reactjs - 正确登录后如何重定向用户?

.htaccess - 避免根级别 301 上的过多重定向

c++ - 这个指针算法是如何工作的?

c++ - 如何启动具有特定访问权限的子进程

c# - Win32 浏览文件夹对话框 : wrong folder returned when user creates a new folder

apache - 使用 Laravel 4 重定向到相对路径

c++ - 在命令行 emacs 中没有使用 cedet 1.1 的自动完成