views:

110

answers:

1

I have this progress bar that uses callback functions from a third party driver, to display a traditional progress bar in a window called CFProgress.

CFProgress *cFM=new CFProgress();
theApp.m_cFM = cFM;
cFM->Create(CFProgress::IDD);
cFM->ShowWindow(SW_SHOW);
thirdpartydriver->set_OnProgress(ProgressFuncC, (void *) cFM);
thirdpartydriver->DoReallyLongTask();

The ProgressFuncC is as follows:

void _stdcall ProgressFuncC(CallbackDataType UserData, LongWord Operation, LongWord Progress, LongWord Total, Bool CanStop, Bool *Stop)
{
 char cMsg[100];
 sprintf_s(cMsg, 100, "Task Progress (%d%% completed).", Progress * 100 / Total);
 CFProgress *cFM;
 cFM = theApp.m_cFM;
 cFM->m_Prg1.SetPos(Progress * 100 / Total);
 cFM->m_lblMsg.SetWindowText(cMsg);
 cFM->UpdateWindow();
}

This used to work well on earlier OS'es, but Windows 7 keeps on complaining that the app is not responding while the progress bar window is displayed. The actual functionality is unaffected.

What would be a good way to make this more responsive to Windows?

Can I add this to the ProgressFuncC code and expect it to resolve the issue, or am I just being confused here :

MSG msg;
if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
{
    if (msg.message == WM_QUIT)
    {
        ::PostMessage(NULL, WM_QUIT, 0, 0L);
    }
    else
    {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }
}
+2  A: 

Is thirdpartydriver->DoReallyLongTask(); running on the main UI thread?

If it is, then your windows won't respond until you return control to the Message Loop.

None of your windows will respond unless this loop is running, and if that long task is on the main thread, then it will block this loop.

while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
}

Your best option is to move your thirdpartydriver->DoReallyLongTask(); into a separate thread, and have your callback function put a message into the message loop (via SendMessage or PostMessage) and then handle that message and update the progress bar.

karoberts
thirdpartydriver->DoReallyLongTask() is indeed running on the main UI thread, as there is no multithreading in the code. But is it not simpler to put the progress bar into a separate thread?
Pranab
It may be simpler, but it won't solve your problem. To get a responsive UI, you MUST return control to the message loop. That is just how windows works.
karoberts
I am new to multithreading - I added a bit of code to the question : "Can I add this to the ProgressFuncC code ..." Do you think that could resolve the unresponsiveness?
Pranab
Yes, that will help. Make it a while loop instead of an if, there might be multiple messages.
karoberts