views:

359

answers:

2

A coworker has been using a custom AVI to indicate progress during some longer operations for years. It's always worked fine.

Recently he decided to move from Delphi 7 to Delphi 2007, in part to get theme support for his applications. (We've finally got most people, but not all, running on XP.) The animation stopped working. Disabling themes makes it work again.

TAnimate is a wrapper around the Windows Animation Control, created using InitCommonControlsEx(ICC_ANIMATE_CLASS). The MSDN documentation says that "If you are using ComCtl32.dll version 6 the thread is not supported, therefore make sure that your application does not block the UI or the animation will not occur." Obviously, this is the intended behavior.

Does anyone have a suggestion for a workaround or alternative to this problem? The processing he's trying to show progress for doesn't lend itself well to spawning a separate thread, and for obvious reasons Application.ProcessMessages is not a good solution either.

EDIT: I'm awarding Rob Kennedy the correct answer to this question, because a) he provided the "missing link" (pun intended) to Raymond Chen's blog post on this topic, and b) because of course moving things to a separate thread was the proper answer.

The ironic thing here: The operation he was conducting that blocked the TAnimate was an indexing operation for a database engine we use (Advantage Database Server, or ADS). He didn't mention that when he came to me with the problem.

ADS supports a progress callback using the TAdsDataSet.AdsRegisterCallbackFunction and TAdsDataSet.AdsClearCallbackFunction methods. The callback function is provided both the progress (in percent) of the current operation and a way to cancel the operation by means of the function's return value. So the entire question turns out to be moot; the callback function can be used to update a progress bar, which indicates to the user that the app isn't hung.

+1  A: 

Raymond Chen has written about this. He doesn't even touch on what I usually think of as the primary reason that a threaded control wouldn't work well, which is that a thread shouldn't draw on a window associated with a different thread.

I encourage your co-worker to revisit whatever it was that made him decide that he couldn't put the task into a separate thread. It's simply not a good idea to block the main UI thread, regardless of whether there's an animation control there to cover up the non-responsiveness.

Rob Kennedy
Rob, thanks. I knew I'd seen something somewhere, but an MSDN search didn't turn up Raymond's article. He's still disagreeing that a separate thread is the only solution (what he's waiting for is happening in a call to a third-party DLL, and his app should NOT be able to continue until that DLL task completes). He just wants to display some kind of activity indicator during the process so the user knows that the app isn't frozen.
Ken White
A: 

As an alternative to TThreads, you can use AsyncCalls which provides an easier entry point into multi-threaded processing from a functional viewpoint. Still, the best way to handle this would be to perform the long process in the background to keep the application responsive.

skamradt