443 lines
12 KiB
C++
443 lines
12 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1998 - 1999
|
|
//
|
|
// File: progress.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
// progress.cpp : implementation file
|
|
//
|
|
|
|
#include <pch.cpp>
|
|
|
|
#pragma hdrstop
|
|
|
|
#include "clibres.h"
|
|
#include "progress.h"
|
|
|
|
// defines
|
|
|
|
#ifdef _DEBUG
|
|
//#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
enum MYDIALOGBEHAVIORENUM
|
|
{
|
|
enumPERCENTCOMPLETEBEHAVIOR = 0,
|
|
enumPROGRESSBARWITHTIMEOUT,
|
|
};
|
|
|
|
typedef struct _PROGRESSPROC_LPARAM
|
|
{
|
|
HINSTANCE hInstance;
|
|
HWND hwndParent;
|
|
UINT iRscJobDescription;
|
|
MYDIALOGBEHAVIORENUM enumWhichBehavior;
|
|
DWORD dwTickerUpperRange;
|
|
DBBACKUPPROGRESS* pdbp;
|
|
} PROGRESSPROC_LPARAM, *PPROGRESSPROC_LPARAM;
|
|
|
|
|
|
static BOOL s_fDisableProgressDialogs = 0;
|
|
static BOOL s_fIKnow = 0;
|
|
|
|
BOOL FICanShowDialogs()
|
|
{
|
|
if (s_fIKnow != TRUE)
|
|
{
|
|
s_fIKnow = TRUE;
|
|
DWORD dwVal;
|
|
|
|
if (S_OK == myGetCertRegDWValue(
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
L"DisableProgress",
|
|
&dwVal))
|
|
{
|
|
s_fDisableProgressDialogs = (dwVal != 0);
|
|
}
|
|
}
|
|
return ! s_fDisableProgressDialogs;
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// show a progress dialog
|
|
|
|
int g_iTimeoutTicks = 0;
|
|
BOOL g_fUseTimer;
|
|
|
|
INT_PTR CALLBACK dlgProcProgress(
|
|
HWND hwndDlg,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam )
|
|
{
|
|
PPROGRESSPROC_LPARAM pLParam = NULL;
|
|
|
|
switch(uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
HWND hwndProgressBar;
|
|
|
|
pLParam = (PPROGRESSPROC_LPARAM)lParam;
|
|
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (ULONG_PTR)pLParam);
|
|
|
|
hwndProgressBar = GetDlgItem(hwndDlg, IDD_PROGRESS_BAR);
|
|
|
|
{
|
|
RECT rcParent, rcDlg, rcScreenArea;
|
|
GetWindowRect(pLParam->hwndParent, &rcParent);
|
|
GetWindowRect(hwndDlg, &rcDlg);
|
|
SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcScreenArea, NULL);
|
|
|
|
// calc centers
|
|
int xLeft = (rcParent.left + rcParent.right) / 2 - (rcDlg.right - rcDlg.left) / 2;
|
|
int yTop = (rcParent.top + rcParent.bottom) / 2 - (rcDlg.bottom - rcDlg.top) / 2;
|
|
|
|
// careful: if the dialog is outside the screen, move it inside
|
|
if (xLeft < rcScreenArea.left)
|
|
xLeft = rcScreenArea.left;
|
|
else if (xLeft + (rcDlg.right - rcDlg.left) > rcScreenArea.right)
|
|
xLeft = rcScreenArea.right - (rcDlg.right - rcDlg.left);
|
|
|
|
if (yTop < rcScreenArea.top)
|
|
yTop = rcScreenArea.top;
|
|
else if (yTop + (rcDlg.bottom - rcDlg.top) > rcScreenArea.bottom)
|
|
yTop = rcScreenArea.bottom - (rcDlg.bottom - rcDlg.top);
|
|
|
|
// map screen coordinates to child coordinates
|
|
SetWindowPos(hwndDlg, HWND_TOPMOST, xLeft, yTop, -1, -1,
|
|
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
}
|
|
|
|
{
|
|
DWORD dwStyle;
|
|
dwStyle = GetWindowLong(hwndProgressBar, GWL_STYLE);
|
|
SetWindowLong(hwndProgressBar, GWL_STYLE, (dwStyle | PBS_SMOOTH));
|
|
}
|
|
|
|
// Set the range and increment of the progress bar.
|
|
if (pLParam->enumWhichBehavior == enumPROGRESSBARWITHTIMEOUT)
|
|
{
|
|
SendMessage(hwndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, pLParam->dwTickerUpperRange));
|
|
SendMessage(hwndProgressBar, PBM_SETSTEP, (WPARAM) 1, 0);
|
|
}
|
|
else
|
|
{
|
|
SendMessage(hwndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 300));
|
|
}
|
|
SendMessage(hwndProgressBar, PBM_SETPOS, (WPARAM)0, 0);
|
|
|
|
// set job description if specified
|
|
if (pLParam->iRscJobDescription != 0)
|
|
{
|
|
WCHAR szJobDesc[MAX_PATH];
|
|
if (0 != LoadString(
|
|
pLParam->hInstance,
|
|
pLParam->iRscJobDescription,
|
|
szJobDesc,
|
|
MAX_PATH))
|
|
SetDlgItemText(hwndDlg, IDC_JOB_DESCRIPTION, szJobDesc);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
case WM_DESTROY:
|
|
{
|
|
pLParam = (PPROGRESSPROC_LPARAM)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
|
|
if (NULL == pLParam)
|
|
break;
|
|
|
|
SetForegroundWindow(pLParam->hwndParent);
|
|
|
|
LocalFree(pLParam);
|
|
pLParam = NULL;
|
|
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, NULL);
|
|
}
|
|
case PBM_STEPIT:
|
|
{
|
|
pLParam = (PPROGRESSPROC_LPARAM)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
|
|
if (NULL == pLParam)
|
|
break;
|
|
|
|
HWND hwndProgressBar = GetDlgItem(hwndDlg, IDD_PROGRESS_BAR);
|
|
|
|
if (pLParam->enumWhichBehavior == enumPROGRESSBARWITHTIMEOUT)
|
|
SendMessage(hwndProgressBar, PBM_STEPIT, 0, 0);
|
|
else
|
|
{
|
|
DWORD wProgress = pLParam->pdbp->dwDBPercentComplete +
|
|
pLParam->pdbp->dwLogPercentComplete +
|
|
pLParam->pdbp->dwTruncateLogPercentComplete ;
|
|
|
|
DWORD wTop = (DWORD)SendMessage(hwndProgressBar,
|
|
PBM_GETRANGE,
|
|
FALSE,
|
|
NULL);
|
|
if (wProgress == wTop)
|
|
{
|
|
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, S_FALSE); // we're done!
|
|
return TRUE;
|
|
}
|
|
else
|
|
SendMessage(hwndProgressBar, PBM_SETPOS, wProgress, 0); // keep incrementing
|
|
}
|
|
|
|
|
|
break;
|
|
}
|
|
case PBM_SETPOS:
|
|
{
|
|
HWND hwndProgressBar = GetDlgItem(hwndDlg, IDD_PROGRESS_BAR);
|
|
LRESULT wTop = SendMessage(hwndProgressBar, PBM_GETRANGE, FALSE, NULL);
|
|
|
|
// if we're not yet at the top make it so
|
|
if (wTop != SendMessage(hwndProgressBar, PBM_GETPOS, 0, 0))
|
|
{
|
|
SendMessage(hwndProgressBar, PBM_SETPOS, (WPARAM)wTop, 0);
|
|
Sleep(400);
|
|
}
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#define PROGRESS_TICKS_PER_SEC 3
|
|
|
|
DWORD WINAPI StartTimerThread( LPVOID lpParameter )
|
|
{
|
|
if (FICanShowDialogs())
|
|
{
|
|
PPROGRESSPROC_LPARAM psParam = (PPROGRESSPROC_LPARAM)lpParameter;
|
|
|
|
HWND hwndProgressDlg = CreateDialogParam(
|
|
psParam->hInstance,
|
|
MAKEINTRESOURCE(IDD_PROGRESS_BOX),
|
|
NULL,
|
|
dlgProcProgress,
|
|
(LPARAM)lpParameter);
|
|
if (NULL == hwndProgressDlg)
|
|
return 0;
|
|
|
|
ShowWindow(hwndProgressDlg, SW_SHOW);
|
|
UpdateWindow(hwndProgressDlg);
|
|
|
|
// if not timer based, go forever
|
|
// if timer based, go while timersec is +
|
|
while ((!g_fUseTimer) ||
|
|
(g_iTimeoutTicks-- > 0))
|
|
{
|
|
SendMessage(hwndProgressDlg, PBM_STEPIT, 0, 0);
|
|
UpdateWindow(hwndProgressDlg);
|
|
Sleep(1000/PROGRESS_TICKS_PER_SEC);
|
|
}
|
|
|
|
// send "fill the indicator"
|
|
SendMessage(hwndProgressDlg, PBM_SETPOS, 0, 0);
|
|
|
|
DestroyWindow(hwndProgressDlg);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// callable APIs: Start/End ProgressDlg
|
|
BOOL FProgressDlgRunning()
|
|
{
|
|
return (!g_fUseTimer || (g_iTimeoutTicks > 0));
|
|
}
|
|
|
|
HANDLE
|
|
StartProgressDlg(
|
|
HINSTANCE hInstance,
|
|
HWND hwndParent,
|
|
DWORD dwTickerSeconds,
|
|
DWORD dwTimeoutSeconds,
|
|
UINT iRscJobDescription)
|
|
{
|
|
HANDLE hProgressThread = NULL;
|
|
DWORD dwThread;
|
|
PPROGRESSPROC_LPARAM psParam = NULL;
|
|
|
|
INITCOMMONCONTROLSEX sCommCtrl;
|
|
sCommCtrl.dwSize = sizeof(sCommCtrl);
|
|
sCommCtrl.dwICC = ICC_PROGRESS_CLASS;
|
|
if (!InitCommonControlsEx(&sCommCtrl))
|
|
goto Ret;
|
|
|
|
g_fUseTimer = dwTimeoutSeconds != 0;
|
|
g_iTimeoutTicks = (dwTimeoutSeconds * PROGRESS_TICKS_PER_SEC);
|
|
|
|
// dialog frees this
|
|
psParam = (PPROGRESSPROC_LPARAM)LocalAlloc(LMEM_FIXED, sizeof(PROGRESSPROC_LPARAM));
|
|
if (psParam == NULL)
|
|
goto Ret;
|
|
|
|
psParam->hInstance = hInstance;
|
|
psParam->hwndParent = hwndParent;
|
|
psParam->enumWhichBehavior = enumPROGRESSBARWITHTIMEOUT;
|
|
psParam->dwTickerUpperRange = dwTickerSeconds * PROGRESS_TICKS_PER_SEC;
|
|
psParam->iRscJobDescription = iRscJobDescription;
|
|
psParam->pdbp = NULL;
|
|
|
|
|
|
hProgressThread =
|
|
CreateThread(
|
|
NULL,
|
|
0,
|
|
StartTimerThread,
|
|
(void*)psParam,
|
|
0,
|
|
&dwThread);
|
|
Ret:
|
|
if (NULL == hProgressThread)
|
|
LocalFree(psParam);
|
|
|
|
return hProgressThread;
|
|
}
|
|
|
|
void EndProgressDlg(HANDLE hProgressThread)
|
|
{
|
|
// end countdown immediately
|
|
g_iTimeoutTicks = 0;
|
|
if (!g_fUseTimer)
|
|
{
|
|
// make the controlling thread suddenly aware of the timer
|
|
g_fUseTimer = TRUE;
|
|
}
|
|
|
|
// don't return until we're certain the progress dlg is gone
|
|
while(TRUE)
|
|
{
|
|
DWORD dwExitCode;
|
|
// break on error
|
|
if (!GetExitCodeThread(hProgressThread, &dwExitCode) )
|
|
break;
|
|
|
|
// continue until goes away
|
|
if (STILL_ACTIVE != dwExitCode)
|
|
break;
|
|
|
|
Sleep(100);
|
|
}
|
|
|
|
CloseHandle(hProgressThread);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////
|
|
// %age complete progress indicator
|
|
|
|
DWORD WINAPI StartPercentCompleteThread( LPVOID lpParameter )
|
|
{
|
|
if (FICanShowDialogs())
|
|
{
|
|
PPROGRESSPROC_LPARAM psParam = (PPROGRESSPROC_LPARAM)lpParameter;
|
|
|
|
HWND hwndProgressDlg = CreateDialogParam(
|
|
psParam->hInstance,
|
|
MAKEINTRESOURCE(IDD_PROGRESS_BOX),
|
|
NULL,
|
|
dlgProcProgress,
|
|
(LPARAM)lpParameter);
|
|
|
|
if (NULL == hwndProgressDlg) {GetLastError(); return 0;}
|
|
|
|
ShowWindow(hwndProgressDlg, SW_SHOW);
|
|
Sleep(0);
|
|
|
|
while (TRUE)
|
|
{
|
|
if (ERROR_SUCCESS != SendMessage(hwndProgressDlg, PBM_STEPIT, 0, 0))
|
|
break;
|
|
|
|
UpdateWindow(hwndProgressDlg);
|
|
Sleep(0);
|
|
Sleep(1000/PROGRESS_TICKS_PER_SEC);
|
|
}
|
|
|
|
// send "fill the indicator"
|
|
SendMessage(hwndProgressDlg, PBM_SETPOS, 0, 0);
|
|
|
|
DestroyWindow(hwndProgressDlg);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
HANDLE
|
|
StartPercentCompleteDlg(
|
|
HINSTANCE hInstance,
|
|
HWND hwndParent,
|
|
UINT iRscJobDescription,
|
|
DBBACKUPPROGRESS *pdbp)
|
|
{
|
|
HANDLE hProgressThread = NULL;
|
|
DWORD dwThread;
|
|
PPROGRESSPROC_LPARAM psParam = NULL;
|
|
|
|
g_fUseTimer = FALSE;
|
|
g_iTimeoutTicks = 0; // no timeout
|
|
|
|
INITCOMMONCONTROLSEX sCommCtrl;
|
|
sCommCtrl.dwSize = sizeof(sCommCtrl);
|
|
sCommCtrl.dwICC = ICC_PROGRESS_CLASS;
|
|
if (!InitCommonControlsEx(&sCommCtrl))
|
|
goto Ret;
|
|
|
|
// dialog frees this
|
|
psParam = (PPROGRESSPROC_LPARAM)LocalAlloc(LMEM_FIXED, sizeof(PROGRESSPROC_LPARAM));
|
|
if (psParam == NULL)
|
|
goto Ret;
|
|
|
|
psParam->hInstance = hInstance;
|
|
psParam->hwndParent = hwndParent;
|
|
psParam->enumWhichBehavior = enumPERCENTCOMPLETEBEHAVIOR;
|
|
psParam->dwTickerUpperRange = 300;
|
|
psParam->iRscJobDescription = iRscJobDescription;
|
|
psParam->pdbp = pdbp;
|
|
|
|
hProgressThread =
|
|
CreateThread(
|
|
NULL,
|
|
0,
|
|
StartPercentCompleteThread,
|
|
(void*)psParam,
|
|
0,
|
|
&dwThread);
|
|
Ret:
|
|
if (NULL == hProgressThread)
|
|
LocalFree(psParam);
|
|
|
|
return hProgressThread;
|
|
}
|
|
|
|
void EndPercentCompleteDlg(HANDLE hProgressThread)
|
|
{
|
|
// don't return until we're certain the progress dlg is gone
|
|
while(TRUE)
|
|
{
|
|
DWORD dwExitCode;
|
|
// break on error
|
|
if (!GetExitCodeThread(hProgressThread, &dwExitCode) )
|
|
break;
|
|
|
|
// continue until goes away
|
|
if (STILL_ACTIVE != dwExitCode)
|
|
break;
|
|
|
|
Sleep(100);
|
|
}
|
|
|
|
CloseHandle(hProgressThread);
|
|
}
|