将stdout重定向到编辑控件(Win32)。马克二世

时间:2011-06-30 08:30:03

标签: c++ winapi redirect

我已经看到了一个完全相同的问题:Redirect stdout to an edit control (Win32)

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

理想情况下,我在想:

  1. 将app的stdout重定向到编辑控件
  2. 运行app并瞧
  3. 但是如果编辑控件的API只允许你写一个字符串,我会想到:

    1 - 将stdout复制到管道输出描述符
    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停止工作:)但那是另一个故事......

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

据我所知,你不能通过管道获得'通知'。如果你想这样做,也许应该使用WM_COPYDATA,这也可以提供更简单的解决方案。当文本发布到您的窗口时,您将收到一条消息,然后您可以将其附加到编辑控件。