我使用SendMessage,但响应似乎被阻止了

I use SendMessage but the responses seem to be blocked

提问人:renfeiyu 提问时间:11/15/2023 最后编辑:renfeiyu 更新时间:11/15/2023 访问量:86

问:

我在RunFactoryTest函数中有很多测试函数要做。它们被放入函数指针 cbTestArray[MAXNUM] 数组中。执行每个函数后,我想立即在 ListView 中显示其返回值。但结果是,在测试运行时,ListView 中不显示任何内容。在所有测试函数完成之前,所有返回值一起显示。

这是我所做的:

typedef bool (*CbFactoryTestFunction)();

void RunFactoryTest(){
    CbFactoryTestFunction cbTestArray[MAXNUM] = {test1,test2,test3...};  //here are the functions used for testing
    bool ret = false;
    LVITEM lvi;  //used to set item in ListView
    for(i = 0;i < MAXNUM;i++)
    {
        ret = cbTestArray[i]();    // test success, show "OK"; fail , show "NG"
            //omit some steps
        
        if(ret){
            lvi.pszText = "OK";
        }else{
            lvi.pszText = "NG";
        }
        SendMessage(hwndListView, LVM_SETITEM, 0, reinterpret_cast<LPARAM>(&lvi));
    }
}

程序运行流畅,结果正确。但是我希望能够在每个测试项目完成后看到结果,而不是等到所有测试项目都完成。

我还尝试创建一个线程来发送消息,但没有用。也许我没有正确使用它。我怎样才能达到我想要的效果?提前感谢您的帮助。

C++ WinAPI

评论

0赞 paddy 11/15/2023
你是怎么调用的?它是否是为了响应窗口消息(例如按钮单击)而调用的?消息泵可能被阻止,这意味着在处理挂起的消息之前,不会重新绘制任何无效的控件。RunFactoryTest
0赞 renfeiyu 11/15/2023
@paddy 是,在响应窗口消息时调用。感谢您的建议,我发现在 SendMessage 之后添加到 ListView 可以立即重新绘制它。这是正确的方法吗?RunFactoryTestUpdateWindow(hwndListView);
1赞 paddy 11/15/2023
这并不理想,但可能已经足够好了。如果您希望长时间运行的任务不会冻结主线程,那么您需要在该任务中的某个位置泵送/调度消息,或者(更准确地说)为任务生成一个线程,并通过 将消息发布回应用程序窗口的队列。例如,您可以发布一条自定义消息,通知测试“X”的结果为“Y”。然后,您的窗口函数将按照您当前正在执行的操作相应地更新列表视图项。PostMessageSendMessage
0赞 IInspectable 11/15/2023
虚拟列表视图控件非常适合列表视图,其数据通过 UI 事件以外的事件进行更改。
0赞 Remy Lebeau 11/15/2023
@IInspectable简单地切换到虚拟 ListView 并不能解决循环阻止 UI 更新的直接问题。必须重新设计代码才能有效地利用虚拟 ListView。

答:

0赞 renfeiyu 12/1/2023 #1

为长时间运行的任务 RunFactoryTest 生成线程是一个理想的解决方案,并且不会阻止 UI 更新。

使用 CreateThread 调用 RunFactoryTest,而不是直接调用它。

HANDLE hThread;
hThread = CreateThread(NULL,0,ThreadFunction,NULL,0,NULL);

在 ThreadFunction 中,调用 RunFactoryTest

DWORD WINAPI ThreadFunction(LPVOID lpParam) {       
    RunFactoryTest();
    return 0;
}