【发布时间】:2011-06-30 08:30:03
【问题描述】:
我已经看到一个与此完全相同的问题:Redirect stdout to an edit control (Win32)
但是,给出的解决方案需要程序员实现一个 my_printf 函数来执行 {printf;从管道读取以编辑控件}。我不能这样做,因为我的 printf 在外部库中。
理想情况下,我正在考虑:
- 将应用的标准输出重定向到编辑控件
- 运行应用,瞧
但如果编辑控件的 API 只允许您向其写入字符串,我会想到类似:
1 - 将标准输出复制到管道输出描述符
3 - 从描述符中的管道读取到缓冲区中
4 - 从缓冲区写入编辑控件
但是,这里缺少第 2 步:
2 - 获得对该管道输出描述符的写入何时完成的信号。
我怎样才能使那部分自动化。我可以在这里使用类似套接字select 的东西吗?
[编辑]
所以,根据 David Heffernan 的 cmets,我会有类似的东西:
#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 停止工作:) 但那是另一个故事......
【问题讨论】:
-
管道
stdout到您的应用程序。阅读stdin并将其发送到编辑控件中。工作完成。 -
@David Heffernan - 我的问题的重点是我应该在哪里阅读
stdin。我的应用程序确实直接写入文本控件。与这些写入交错,我将从外部库中获得另一个写入stdout。您如何看待让工作线程不断读取stdin并写入编辑控件? -
我会在工作线程中读取标准输入,并在管道为空时让它阻塞。然后,您需要使用 windows 消息将文本发送到主线程中的窗口,以便您遵守 windows 的线程关联。
-
@David Heffernan - 对于块,我可以在描述符中的管道上使用 WaitForSingleObject 吗? windows消息你指的是GetMessage、DispatchMessage等Win API?
-
ReadFile阻塞,直到有数据要读取。GetMessage/DispatchMessage已经存在于您的应用程序中,因为您有一个编辑控件。使用SendMessage发送消息。