Перенаправить стандартный вывод в элемент управления редактирования (Win32).Марк II - PullRequest
1 голос
/ 30 июня 2011

Я видел вопрос, точно такой, как этот, уже существует: Перенаправление stdout в элемент управления редактирования (Win32)

Однако, для решения, указанного для этого, программист должен реализовать my_printfфункция, которая делает {printf;читать из трубы для редактирования контроля}.Я не могу этого сделать, потому что мои printf находятся во внешней библиотеке.

В идеале я думаю о:

  1. перенаправить стандартный вывод приложения для редактирования элемента управления
  2. запустить приложениеи вуаля

Но если API управления редактирования позволяет только записать в него строку, я бы подумал о чем-то вроде:

1 - дублирование stdout в дескриптор конвейера
3 - чтение из канала в дескрипторе в буфер
4 - запись из буфера для редактирования элемента управления

Однако, там пропущен шаг 2:

2 - получениесигнал о том, когда запись в этот дескриптор конвейера завершена.

Как я могу автоматизировать эту часть.Могу ли я использовать что-то вроде сокета select здесь?

[EDIT]

Итак, согласно комментариям Дэвида Хеффернана, у меня будет что-то вроде:

  #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, libcurl перестает работать :) Но это другая история ...

Ответы [ 2 ]

2 голосов
/ 04 июля 2011

Windows поддерживает асинхронный ввод / вывод.Это упрощает:

  1. дублирование stdout в дескриптор конвейера
  2. Выпуск асинхронного чтения из канала в дескрипторе в буфер
  3. Ожидание сообщения или события(MsgWaitForMultipleObjects).
    • Если ожидание заканчивается одним или несколькими сообщениями, позвоните PeekMessage(PM_REMOVE), чтобы удалить их.
    • Если сигнализируется событие канала, скопируйте текст из буфера для редактирования элемента управления.
1 голос
/ 30 июня 2011

Насколько я знаю, вы не можете получать "уведомления" с помощью канала. Если вы действительно хотите это сделать, возможно, вам следует использовать вместо него WM_COPYDATA, что также обеспечит более простое решение. Когда текст будет опубликован в вашем окне, вы получите сообщение, которое затем сможете добавить в элемент управления для редактирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...