首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么是正确使用WTL CIdleHandler?

什么是正确使用WTL CIdleHandler?
EN

Stack Overflow用户
提问于 2017-09-19 22:49:16
回答 1查看 438关注 0票数 2

我正在尝试学习WTL / Win32编程,但我不太理解CIdleHandler mixin类的设计。

对于WTL 9.1,CMessageLoop代码如下(来自atlapp.h):

代码语言:javascript
复制
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;
        }
    }

对空闲处理程序的实际调用非常简单。

代码语言:javascript
复制
// 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的调用一样

代码语言:javascript
复制
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;
}

我的分析如下:在每次“干旱”(不向Win32应用程序发送消息)期间,都调用OnIdle处理程序。

但为什么只有一次?如果是PeekMessage,您不希望后台空闲任务被一次又一次地调用吗?而且,在我看来,奇怪的是,WM_LBUTTONDOWN (用户在窗口上左键单击了一些东西)会激活空闲处理(bDoIdle = True),但是WM_MOUSEMOVE被明确地呼出以防止空闲处理的重新激活。

有人能给我WTL循环的“适当”使用场景(或者更具体地说: CIdleHandler)吗?我想我的期望是,空闲处理功能将是小的,增量的任务,只需说.100毫秒完成。然后他们就会在后台被反复呼叫。

但在WTL中,情况似乎并非如此。还是我还没完全理解闲置循环?因为如果我有一个增量的后台任务注册为CIdleHandler..。然后,如果用户离开窗口,任务将只运行一次!如果没有注入到系统中的任何消息(如WM_LBUTTONDOWN),bDoIdle变量将始终保持为false!

有谁能很好地解释这一切吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-20 06:04:47

正如注释中所述,OnIdle处理程序应该在某些活动(尤指p)之后空转开始时调用。以便更新UI。这解释了对处理程序的“一次”调用:发生了一些事情,然后您就有机会更新UI元素。如果您需要正在进行的后台处理,您应该使用计时器或工作线程。

WTL示例建议使用空闲处理程序,例如在样品\Alpha\mainfrm.h中。

Window类获取线程的消息循环并请求空闲更新:

代码语言:javascript
复制
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
    // ...

    // register object for message filtering and idle updates
    CMessageLoop* pLoop = _Module.GetMessageLoop();
    ATLASSERT(pLoop != NULL);
    pLoop->AddMessageFilter(this);
    pLoop->AddIdleHandler(this);

稍后,在消息处理和用户交互之后,空闲处理程序更新工具栏以反映可能的状态更改:

代码语言:javascript
复制
virtual BOOL OnIdle()
{
    UIUpdateToolBar();
    return FALSE;
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46310784

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档