2011-06-30 14 views
1

私は、まさにこのような質問が既に存在して見てきました:Redirect stdout to an edit control (Win32)stdoutを編集コントロール(Win32)にリダイレクトします。マークII

をしかし、与えられた解決策は、{のprintfを行うmy_printf機能を実装するために、プログラマが必要です。コントロールを編集するためにパイプから読み込む}。私のprintfは外部のライブラリにあるので、私はそれを行うことはできません。

理想的には、私はと思っています:

制御

  • 実行アプリと出来上がりを編集する

    1. リダイレクトアプリのstdoutしかし、エディットコントロールのAPIは、あなたがに文字列を書き込むことができた場合それは私のようなものだと思うだろう:

      1 - dup'ing stdout to pipe out記述子
      3 - バッファ
      4にcriptor - 制御

      を編集するために、バッファからの書き込みは、しかし、行方不明のステップ2がそこにある:

      2 - そのパイプへの書き込みアウトディスクリプタが行われたときの信号を得ます。

      どうすればその部分を自動化できますか?ソケットselectのようなものをここで使用できますか? AppendLogがエディットコントロールに文字列を書き込み

      #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); 
          } 
          } 
      

      :だから

      [EDIT]

      は、デビッドHeffernanの者のコメントによると、私のようなものを持っているでしょう。

      [EDIT]

      このコードは正しく動作します。 libcurlからstdoutのトレースをリダイレクトすると、libcurlは動作を停止します:)しかし、それは別の話です...

  • +0

    あなたのアプリに 'stdout'をパイプします。 'stdin'を読み込み、それを編集コントロールに吐き出します。ジョブが完了しました。 –

    +0

    @David Heffernan - 私の質問のポイントは、どこで 'stdin'を読むべきですか?私のアプリはテキストコントロールに直接書き込む。この書き込みをインターリーブして、外部ライブラリから 'stdout'への別の書き込みを取得します。 'stdin'を読んでエディットコントロールに書き込んでいるワーカースレッドを常に持っていることはどう思いますか? – rturrado

    +0

    私は作業スレッドでstdinの読み取りを行い、パイプが空のときにブロックさせます。ウィンドウのメッセージを使用してメインスレッドのウィンドウにテキストを送信する必要があるため、ウィンドウのスレッドアフィニティを遵守する必要があります。 –

    答えて

    1

    私が知っている限り、パイプで「通知」を受け取ることはできません。おそらくWM_COPYDATAを使用して、より簡単な解決策を提供する必要があるかもしれません。テキストがウィンドウにポストされるとメッセージが表示され、エディットコントロールに追加することができます。

    +0

    確かにReadFileは何かが読まれるまでブロックします。 –

    +0

    はい、彼が言及している 'シグナル'はWindowsのメッセージだと仮定しました。もしあなたがパイプを使い、WMを望むのであれば、自分でそれを生成する必要があります。 –

    +0

    ReadFileがエラーコードを返して、パイプが閉じられていて十分な信号であることを示していると思います。あなたがパイプを使用しているなら、私はWindowsメッセージの必要性を見ません。 –

    2

    Windowsは非同期I/Oをサポートしています。それはそれは簡単です:

    1. が非同期メッセージやイベント(MsgWaitForMultipleObjects)のバッファ
    2. 待ちに記述子にパイプから読み込まパイプに記述
    3. 問題を標準出力を出しdup'ing。
      • 1つ以上のメッセージで終了する場合は、PeekMessage(PM_REMOVE)に電話をかけて削除してください。
      • パイプイベントが通知された場合は、バッファから編集コントロールにテキストをコピーします。
    +0

    私はマイクの選択のために行ったので、私は彼の答えを受け入れた。ありがとう。 – rturrado

    関連する問題