[PATCH v2] browseui: Implement PROGDLG_AUTOTIME flag for IProgressDialog.

Alistair Leslie-Hughes leslie_alistair at hotmail.com
Mon Oct 22 22:18:38 CDT 2018


From: Michael Müller <michael at fds-team.de>

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45970
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
---
v2: Use FormatMessage.

 dlls/browseui/browseui.rc   |  5 ++++
 dlls/browseui/progressdlg.c | 73 +++++++++++++++++++++++++++++++++++++++++----
 dlls/browseui/resids.h      |  5 ++++
 3 files changed, 78 insertions(+), 5 deletions(-)

diff --git a/dlls/browseui/browseui.rc b/dlls/browseui/browseui.rc
index 4c612e9..e33b2ad 100644
--- a/dlls/browseui/browseui.rc
+++ b/dlls/browseui/browseui.rc
@@ -25,6 +25,11 @@ LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
 STRINGTABLE
 {
     IDS_CANCELLING    "Canceling..."
+    IDS_REMAINING1    "%1!u! %2 remaining"
+    IDS_REMAINING2    "%1!u! %2 and %3!u! %4 remaining"
+    IDS_SECONDS       "seconds"
+    IDS_MINUTES       "minutes"
+    IDS_HOURS         "hours"
 }
 
 IDD_PROGRESS_DLG DIALOG 0, 0, 260, 85
diff --git a/dlls/browseui/progressdlg.c b/dlls/browseui/progressdlg.c
index 2355b0c..e10d8bd 100644
--- a/dlls/browseui/progressdlg.c
+++ b/dlls/browseui/progressdlg.c
@@ -74,6 +74,9 @@ typedef struct tagProgressDialog {
     ULONGLONG ullCompleted;
     ULONGLONG ullTotal;
     HWND hwndDisabledParent;    /* For modal dialog: the parent that need to be re-enabled when the dialog ends */
+    ULONGLONG startTime;
+    LPWSTR remainingMsg[2];
+    LPWSTR timeMsg[3];
 } ProgressDialog;
 
 static inline ProgressDialog *impl_from_IProgressDialog(IProgressDialog *iface)
@@ -158,6 +161,22 @@ static void update_dialog(ProgressDialog *This, DWORD dwUpdate)
     }
 }
 
+static void load_time_strings(ProgressDialog *This)
+{
+    int i;
+
+    for (i = 0; i < 2; i++)
+    {
+        if (!This->remainingMsg[i])
+            This->remainingMsg[i] = load_string(BROWSEUI_hinstance, IDS_REMAINING1 + i);
+    }
+    for (i = 0; i < 3; i++)
+    {
+        if (!This->timeMsg[i])
+            This->timeMsg[i] = load_string(BROWSEUI_hinstance, IDS_SECONDS + i);
+    }
+}
+
 static void end_dialog(ProgressDialog *This)
 {
     SendMessageW(This->hwnd, WM_DLG_DESTROY, 0, 0);
@@ -260,14 +279,18 @@ static DWORD WINAPI dialog_thread(LPVOID lpParameter)
 
 static void ProgressDialog_Destructor(ProgressDialog *This)
 {
+    int i;
     TRACE("destroying %p\n", This);
     if (This->hwnd)
         end_dialog(This);
-    heap_free(This->lines[0]);
-    heap_free(This->lines[1]);
-    heap_free(This->lines[2]);
+    for (i = 0; i < 3; i++)
+        heap_free(This->lines[i]);
     heap_free(This->cancelMsg);
     heap_free(This->title);
+    for (i = 0; i < 2; i++)
+        heap_free(This->remainingMsg[i]);
+    for (i = 0; i < 3; i++)
+        heap_free(This->timeMsg[i]);
     This->cs.DebugInfo->Spare[0] = 0;
     DeleteCriticalSection(&This->cs);
     heap_free(This);
@@ -329,8 +352,6 @@ static HRESULT WINAPI ProgressDialog_StartProgressDialog(IProgressDialog *iface,
     TRACE("(%p, %p, %x, %p)\n", iface, punkEnableModeless, dwFlags, reserved);
     if (punkEnableModeless || reserved)
         FIXME("Reserved parameters not null (%p, %p)\n", punkEnableModeless, reserved);
-    if (dwFlags & PROGDLG_AUTOTIME)
-        FIXME("Flags PROGDLG_AUTOTIME not supported\n");
     if (dwFlags & PROGDLG_NOTIME)
         FIXME("Flags PROGDLG_NOTIME not supported\n");
 
@@ -365,6 +386,10 @@ static HRESULT WINAPI ProgressDialog_StartProgressDialog(IProgressDialog *iface,
             This->hwndDisabledParent = hwndDisable;
     }
 
+    if (dwFlags & PROGDLG_AUTOTIME)
+        load_time_strings(This);
+
+    This->startTime = GetTickCount64();
     LeaveCriticalSection(&This->cs);
 
     return S_OK;
@@ -422,6 +447,42 @@ static BOOL WINAPI ProgressDialog_HasUserCancelled(IProgressDialog *iface)
     return This->isCancelled;
 }
 
+static void update_time_remaining(ProgressDialog *This, ULONGLONG ullCompleted, ULONGLONG ullTotal)
+{
+    unsigned int remaining, remainder = 0;
+    ULONGLONG elapsed;
+    WCHAR line[128];
+    int i;
+    DWORD_PTR args[4];
+
+    if (!This->startTime || !ullCompleted || !ullTotal)
+        return;
+
+    elapsed = GetTickCount64() - This->startTime;
+    remaining = (elapsed * ullTotal / ullCompleted - elapsed) / 1000;
+
+    for (i = 0; remaining >= 60 && i < 2; i++)
+    {
+        remainder = remaining % 60;
+        remaining /= 60;
+    }
+
+    args[0] = remaining;
+    args[1] = (DWORD_PTR)This->timeMsg[i];
+    args[2] = remainder;
+    args[3] = (DWORD_PTR)This->timeMsg[i-1];
+
+    if (i > 0 && remaining < 2 && remainder != 0)
+        FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
+               This->remainingMsg[1], 0, 0, line, ARRAY_SIZE(line), (__ms_va_list*)args);
+    else
+        FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
+               This->remainingMsg[0], 0, 0, line, ARRAY_SIZE(line), (__ms_va_list*)args);
+
+    set_buffer(&This->lines[2], line);
+    This->dwUpdate |= UPDATE_LINE3;
+}
+
 static HRESULT WINAPI ProgressDialog_SetProgress64(IProgressDialog *iface, ULONGLONG ullCompleted, ULONGLONG ullTotal)
 {
     ProgressDialog *This = impl_from_IProgressDialog(iface);
@@ -434,6 +495,8 @@ static HRESULT WINAPI ProgressDialog_SetProgress64(IProgressDialog *iface, ULONG
     This->ullCompleted = ullCompleted;
     This->dwUpdate |= UPDATE_PROGRESS;
     hwnd = This->hwnd;
+    if (This->dwFlags & PROGDLG_AUTOTIME)
+        update_time_remaining(This, ullCompleted, ullTotal);
     LeaveCriticalSection(&This->cs);
 
     if (hwnd)
diff --git a/dlls/browseui/resids.h b/dlls/browseui/resids.h
index cd44a8e..865cdd1 100644
--- a/dlls/browseui/resids.h
+++ b/dlls/browseui/resids.h
@@ -21,6 +21,11 @@
 #include "commctrl.h"
 
 #define IDS_CANCELLING      16
+#define IDS_REMAINING1      17
+#define IDS_REMAINING2      18
+#define IDS_SECONDS         19
+#define IDS_MINUTES         20
+#define IDS_HOURS           21
 
 #define IDC_ANIMATION           100
 #define IDC_PROGRESS_BAR        102
-- 
1.9.1



More information about the wine-devel mailing list