我将尝试学习WTL/Win32编程,但我并不完全理解CIdleHandler mixin类的设计。
对于WTL 9.1版本,CMessageLoop代码如下(来自atlapp.h):
实际调用空闲处理程序非常简单。
我的分析如下:在“PeekMessage Drought”(Win32应用程序没有接收到消息的时间段)期间,OnIdle处理程序被调用一次。
但为什么只有一次呢?在PeekMessage情况下,难道不希望后台空闲任务不断地被调用吗?此外,对我来说,WM_LBUTTONDOWN(用户在窗口上单击某物)会激活空闲处理(bDoIdle = True),但明确禁止调用WM_MOUSEMOVE以防止重新激活空闲处理,这似乎很奇怪。
有人可以给我WTL空闲循环(或更具体地说:CIdleHandler)的“正确”使用场景吗?我猜我的期望是空闲处理函数将是小的、增量式的任务,不超过100ms即可完成。然后它们会在后台重复调用。
但在WTL中似乎不是这种情况。或者我没有完全理解空闲循环?因为如果我将增量式后台任务注册为CIdleHandler……那么如果用户离开窗口,任务只会运行一次!如果没有向系统发送任何消息(例如WM_LBUTTONDOWN),则bDoIdle变量将永远保持false!
有人能对这一切做出好的解释吗?
对于WTL 9.1版本,CMessageLoop代码如下(来自atlapp.h):
for(;;)
{
while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
{
if(!OnIdle(nIdleCount++))
bDoIdle = FALSE;
}
bRet = ::GetMessage(&m_msg, NULL, 0, 0);
if(bRet == -1)
{
ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n"));
continue; // error, don't process
}
else if(!bRet)
{
ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n"));
break; // WM_QUIT, exit message loop
}
if(!PreTranslateMessage(&m_msg))
{
::TranslateMessage(&m_msg);
::DispatchMessage(&m_msg);
}
if(IsIdleMessage(&m_msg))
{
bDoIdle = TRUE;
nIdleCount = 0;
}
}
实际调用空闲处理程序非常简单。
// override to change idle processing
virtual BOOL OnIdle(int /*nIdleCount*/)
{
for(int i = 0; i < m_aIdleHandler.GetSize(); i++)
{
CIdleHandler* pIdleHandler = m_aIdleHandler[i];
if(pIdleHandler != NULL)
pIdleHandler->OnIdle();
}
return FALSE; // don't continue
}
现在我们需要调用IsIdleMessage函数
static BOOL IsIdleMessage(MSG* pMsg)
{
// These messages should NOT cause idle processing
switch(pMsg->message)
{
case WM_MOUSEMOVE:
#ifndef _WIN32_WCE
case WM_NCMOUSEMOVE:
#endif // !_WIN32_WCE
case WM_PAINT:
case 0x0118: // WM_SYSTIMER (caret blink)
return FALSE;
}
return TRUE;
}
我的分析如下:在“PeekMessage Drought”(Win32应用程序没有接收到消息的时间段)期间,OnIdle处理程序被调用一次。
但为什么只有一次呢?在PeekMessage情况下,难道不希望后台空闲任务不断地被调用吗?此外,对我来说,WM_LBUTTONDOWN(用户在窗口上单击某物)会激活空闲处理(bDoIdle = True),但明确禁止调用WM_MOUSEMOVE以防止重新激活空闲处理,这似乎很奇怪。
有人可以给我WTL空闲循环(或更具体地说:CIdleHandler)的“正确”使用场景吗?我猜我的期望是空闲处理函数将是小的、增量式的任务,不超过100ms即可完成。然后它们会在后台重复调用。
但在WTL中似乎不是这种情况。或者我没有完全理解空闲循环?因为如果我将增量式后台任务注册为CIdleHandler……那么如果用户离开窗口,任务只会运行一次!如果没有向系统发送任何消息(例如WM_LBUTTONDOWN),则bDoIdle变量将永远保持false!
有人能对这一切做出好的解释吗?