void OneThreadclass::Idle(
UInt32 milliseconds)
{
DWORD done = timeGetTime() + milliseconds;
do
{
Sleep(1); // yield to all threads // NOTE: PeekMessage() does the following:
// 1. Permits any queued SendMessage() calls to windows owned by this thread to execute.
// 2. Effectively yields execution to other threads waiting for this thread to go idle.
// 3. Applications simply wishing to yield the remainder of their timeslice should call Sleep(0).
MSG msg;
PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
}
while (timeGetTime() < done);
}
请问这里PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);起了什么作用?光收了消息,然后什么都没做。放在这里干嘛?
UInt32 milliseconds)
{
DWORD done = timeGetTime() + milliseconds;
do
{
Sleep(1); // yield to all threads // NOTE: PeekMessage() does the following:
// 1. Permits any queued SendMessage() calls to windows owned by this thread to execute.
// 2. Effectively yields execution to other threads waiting for this thread to go idle.
// 3. Applications simply wishing to yield the remainder of their timeslice should call Sleep(0).
MSG msg;
PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
}
while (timeGetTime() < done);
}
请问这里PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);起了什么作用?光收了消息,然后什么都没做。放在这里干嘛?
* Posted messages
* Input (hardware) messages and system internal events
* Sent messages (again)
* WM_PAINT messages
* WM_TIMER messages
如果这里没有PeekMessage ,那么在跳出循环前,会占用大量cpu的工作时间。
如果你在一个主线程里面开了如下一个循环,则程序就不会响应其他任何windows消息:for (;;)
{
//其他代码
...
Sleep(100);
}如果必须实时响应windows,则必须如下写,你可以做个测试.for (;;)
{
//其他代码
...
MSG msg;
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} Sleep(100);
}
GetMessage :过门不入,操作系统再去照顾其它人 PeekMessage:取会控制权,使程序得以执行一段时间.
windows核心编程上面讲的很详细呀.
“如果别的程序或者线程向这个Thread发个Message,就死等了。比如一个简单的GetWindowText(或者直接显式的调用SendMessage(..., WM_GETTEXT,...,...)就不动了,...,所以歇的时候一定不能堵住SendMessage。”PeekMessage的确有“让其他线程向此线程SendMessage过来不阻塞的功效”。谢谢。
现在我有一个问题:试验中,我发现PeekMessage里的 LOWORD(msg.message)收不到自线程发过来的WM_GETTEXT这个消息,不知道为何?unsigned __stdcall SubThreadFun( void* pArguments )
{
DWORD done;
done = timeGetTime() + 3000;
while (timeGetTime() != done)
{
} HWND mywnd = (HWND)pArguments; char strWindowText[80];
// GetWindowText(mywnd, strWindowText, 100); //will also send WM_GETTEXT
::SendMessage(mywnd, WM_GETTEXT, 100, (LPARAM)strWindowText);
MessageBox(NULL, strWindowText, "MainWindowText is:", 0); _endthreadex( 0 );
return 0;
}
主线程如下:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc; switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
//DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
DWORD done;
done = timeGetTime() + 8000;
do
{
Sleep(1);
MSG msg;
if (PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE))
{
char outbuff[80];
sprintf(outbuff, "%d", msg.message);
OutputDebugString(outbuff); OutputDebugString("\n");
WORD lowword1 = LOWORD(msg.message);
if (lowword1 == WM_GETTEXT) //就是这里,收不到WM_GETTEXT,奇怪
{
int a, b =3;
a = b;
MessageBox(NULL, "I am here", "I am here", 0);
}
}
}
while (timeGetTime() < done); MessageBox(NULL, "while finished", "while finished", 0); break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case IDM_startsubthread:
hThread = (HANDLE)_beginthreadex( NULL, 0, &SubThreadFun, (void*)hWnd, 0, &threadID );
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_GETTEXT:
break; //add for test
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Maybe that'll just be fine, you can do that in theory. But remember this:
"The PeekMessage function dispatches incoming sent messages, checks the thread message queue for a posted message, and retrieves the message (if any exist)."which means, sent messages(those transferred by SendMessage() or equivalent) will be "internally and directly" diapatched to your WndProc, and you can never "Peek" or "Get" it out.