From e49cde166f187714e954d41cf0ed79414d0fca23 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 31 Oct 2017 17:10:41 +0100 Subject: [PATCH] Improve progress bar updating in native wxMSW wxProgressDialog Since the switch to tying the task dialog thread message queue with the main thread, animating the progress bar didn't work well unless the dialog was updated very frequently from the main thread and could lag behind significantly, and confusingly for the user, otherwise. Work around this by avoiding the progress bar animation and setting it immediately to its real value. This works much better in practice. --- src/msw/progdlg.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/msw/progdlg.cpp b/src/msw/progdlg.cpp index 6c6e6e0bfe..9d222beec1 100644 --- a/src/msw/progdlg.cpp +++ b/src/msw/progdlg.cpp @@ -214,6 +214,33 @@ void PerformNotificationUpdates(HWND hwnd, if ( sharedData->m_notifications & wxSPDD_VALUE_CHANGED ) { + // Use a hack to avoid progress bar animation: we can't afford to use + // it because animating the gauge movement smoothly requires a + // constantly running message loop and while it does run in this (task + // dialog) thread, it is often blocked from proceeding by some lock + // held by the main thread which is busy doing something and may not + // dispatch events frequently enough. So, in practice, the animation + // can lag far behind the real value and results in showing a wrong + // value in the progress bar. + // + // To prevent this from happening, set the progress bar value to + // something greater than its maximal value and then move it back: in + // the current implementations of the progress bar control, moving its + // position backwards does it directly, without using the animation, + // which is exactly what we want here. + // + // Finally notice that this hack doesn't really work for the last + // value, but while we could use a nested hack and temporarily increase + // the progress bar range when the value is equal to it, it isn't + // actually necessary in practice because when we reach the end of the + // bar the dialog is either hidden immediately anyhow or the main + // thread enters a modal event loop which does dispatch events and so + // it's not a problem to have an animated transition in this particular + // case. + ::SendMessage( hwnd, + TDM_SET_PROGRESS_BAR_POS, + sharedData->m_value + 1, + 0 ); ::SendMessage( hwnd, TDM_SET_PROGRESS_BAR_POS, sharedData->m_value,