You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
802 lines
18 KiB
802 lines
18 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
progbar.c
|
|
|
|
Abstract:
|
|
|
|
Centralizes access to the progress bar and associated messages accross components
|
|
(hwcomp,migapp,etc.) and sides (w9x, nt)
|
|
|
|
Author:
|
|
|
|
Marc R. Whitten (marcw) 14-Apr-1997
|
|
|
|
Revision History:
|
|
|
|
jimschm 19-Jun-1998 Improved to allow revision of estimates, necessary
|
|
for NT-side progress bar.
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
#include "migshared.h"
|
|
|
|
//
|
|
// Types
|
|
//
|
|
|
|
typedef struct {
|
|
BOOL Started;
|
|
BOOL Completed;
|
|
UINT InitialGuess;
|
|
UINT TotalTicks;
|
|
UINT TicksSoFar;
|
|
UINT LastTickDisplayed;
|
|
} SLICE, *PSLICE;
|
|
|
|
typedef struct {
|
|
HWND Window;
|
|
HANDLE CancelEvent;
|
|
PCSTR Message;
|
|
DWORD MessageId;
|
|
DWORD Delay;
|
|
BOOL InUse;
|
|
} DELAYTHREADPARAMS, *PDELAYTHREADPARAMS;
|
|
|
|
|
|
#if 0
|
|
|
|
typedef struct {
|
|
HANDLE CancelEvent;
|
|
DWORD TickCount;
|
|
BOOL InUse;
|
|
} TICKTHREADPARAMS, *PTICKTHREADPARAMS;
|
|
|
|
#endif
|
|
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
BOOL g_ProgBarInitialized = FALSE;
|
|
|
|
HWND g_ProgressBar;
|
|
HWND g_Component;
|
|
HWND g_SubComponent;
|
|
|
|
PBRANGE g_OrgRange;
|
|
|
|
HANDLE g_ComponentCancelEvent;
|
|
HANDLE g_SubComponentCancelEvent;
|
|
|
|
BOOL *g_CancelFlagPtr;
|
|
GROWBUFFER g_SliceArray;
|
|
UINT g_SliceCount;
|
|
UINT g_MaxTickCount;
|
|
UINT g_PaddingTicks;
|
|
UINT g_CurrentTickCount;
|
|
UINT g_CurrentPos;
|
|
UINT g_ReduceFactor;
|
|
BOOL g_Reverse = FALSE;
|
|
OUR_CRITICAL_SECTION g_ProgBarCriticalSection;
|
|
UINT g_CurrentSliceId = (UINT)-1;
|
|
|
|
//
|
|
// Tuning constants
|
|
//
|
|
|
|
#define TICKSCALE 100
|
|
|
|
|
|
//
|
|
// Implementaiton
|
|
//
|
|
|
|
VOID
|
|
InitializeProgressBar (
|
|
IN HWND ProgressBar,
|
|
IN HWND Component, OPTIONAL
|
|
IN HWND SubComponent, OPTIONAL
|
|
IN BOOL *CancelFlagPtr OPTIONAL
|
|
)
|
|
{
|
|
LONG rc;
|
|
CHAR Data[256];
|
|
DWORD Size;
|
|
HKEY Key;
|
|
|
|
g_ProgressBar = ProgressBar;
|
|
g_CancelFlagPtr = CancelFlagPtr;
|
|
|
|
g_ProgBarInitialized = TRUE;
|
|
|
|
SendMessage (ProgressBar, PBM_SETPOS, 0, 0);
|
|
g_CurrentPos = 0;
|
|
SendMessage (ProgressBar, PBM_GETRANGE, 0, (LPARAM) &g_OrgRange);
|
|
|
|
//
|
|
// Create cancel events for delayed messages.
|
|
//
|
|
g_ComponentCancelEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
|
|
g_SubComponentCancelEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
|
|
|
|
if (!g_ComponentCancelEvent || !g_SubComponentCancelEvent) {
|
|
DEBUGMSG ((DBG_ERROR, "ProgressBar: Could not create cancel events."));
|
|
}
|
|
|
|
InitializeOurCriticalSection (&g_ProgBarCriticalSection);
|
|
|
|
g_Component = Component;
|
|
g_SubComponent = SubComponent;
|
|
|
|
DEBUGMSG_IF ((
|
|
Component && !IsWindow (Component),
|
|
DBG_WHOOPS,
|
|
"Progress bar component is not a valid window"
|
|
));
|
|
|
|
DEBUGMSG_IF ((
|
|
SubComponent && !IsWindow (SubComponent),
|
|
DBG_WHOOPS,
|
|
"Progress bar sub component is not a valid window"
|
|
));
|
|
|
|
MYASSERT (!g_SliceCount);
|
|
MYASSERT (!g_SliceArray.Buf);
|
|
MYASSERT (!g_MaxTickCount);
|
|
MYASSERT (!g_PaddingTicks);
|
|
MYASSERT (!g_CurrentTickCount);
|
|
MYASSERT (g_CurrentSliceId == (UINT)-1);
|
|
|
|
g_ReduceFactor = 1;
|
|
|
|
Key = OpenRegKeyStrA ("HKLM\\inapoi");
|
|
if (Key) {
|
|
Size = 256;
|
|
rc = RegQueryValueExA (Key, "", NULL, NULL, (PBYTE) Data, &Size);
|
|
CloseRegKey (Key);
|
|
|
|
#pragma prefast(suppress:400, "not concerned about different code page")
|
|
if (rc == ERROR_SUCCESS && !lstrcmpiA (Data, "backwards")) {
|
|
g_Reverse = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
TerminateProgressBar (
|
|
VOID
|
|
)
|
|
{
|
|
if (g_ComponentCancelEvent) {
|
|
CloseHandle (g_ComponentCancelEvent);
|
|
g_ComponentCancelEvent = NULL;
|
|
}
|
|
|
|
if (g_SubComponentCancelEvent) {
|
|
CloseHandle (g_SubComponentCancelEvent);
|
|
g_SubComponentCancelEvent = NULL;
|
|
}
|
|
|
|
DeleteOurCriticalSection (&g_ProgBarCriticalSection);
|
|
|
|
FreeGrowBuffer (&g_SliceArray);
|
|
g_SliceCount = 0;
|
|
g_MaxTickCount = 0;
|
|
g_PaddingTicks = 0;
|
|
g_CurrentTickCount = 0;
|
|
g_CurrentSliceId = -1;
|
|
g_Component = NULL;
|
|
g_SubComponent = NULL;
|
|
|
|
g_ReduceFactor = 1;
|
|
|
|
SendMessage (g_ProgressBar, PBM_SETRANGE32, g_OrgRange.iLow, g_OrgRange.iHigh);
|
|
|
|
g_ProgBarInitialized = FALSE;
|
|
}
|
|
|
|
|
|
UINT
|
|
RegisterProgressBarSlice (
|
|
IN UINT InitialEstimate
|
|
)
|
|
{
|
|
PSLICE Slice;
|
|
UINT SliceId;
|
|
|
|
MYASSERT (g_ProgBarInitialized);
|
|
if (!g_ProgBarInitialized) {
|
|
return 0;
|
|
}
|
|
|
|
SliceId = g_SliceCount;
|
|
|
|
Slice = (PSLICE) GrowBuffer (&g_SliceArray, sizeof (SLICE));
|
|
g_SliceCount++;
|
|
|
|
Slice->Started = FALSE;
|
|
Slice->Completed = FALSE;
|
|
Slice->TotalTicks = InitialEstimate * TICKSCALE;
|
|
Slice->InitialGuess = Slice->TotalTicks;
|
|
Slice->TicksSoFar = 0;
|
|
Slice->LastTickDisplayed = 0;
|
|
|
|
return SliceId;
|
|
}
|
|
|
|
|
|
VOID
|
|
ReviseSliceEstimate (
|
|
IN UINT SliceId,
|
|
IN UINT RevisedEstimate
|
|
)
|
|
{
|
|
PSLICE Slice;
|
|
|
|
MYASSERT (g_ProgBarInitialized);
|
|
if (!g_ProgBarInitialized) {
|
|
return;
|
|
}
|
|
|
|
if (SliceId >= g_SliceCount) {
|
|
DEBUGMSG ((DBG_WHOOPS, "ReviseSliceEstimate: Invalid slice ID %u", SliceId));
|
|
return;
|
|
}
|
|
|
|
Slice = (PSLICE) g_SliceArray.Buf + SliceId;
|
|
|
|
if (!g_CurrentTickCount) {
|
|
Slice->TotalTicks = RevisedEstimate;
|
|
return;
|
|
}
|
|
|
|
if (Slice->Completed) {
|
|
DEBUGMSG ((DBG_WHOOPS, "ReviseSliceEstimate: Can't revise completed slice"));
|
|
return;
|
|
}
|
|
|
|
if (Slice->InitialGuess == 0) {
|
|
return;
|
|
}
|
|
|
|
RevisedEstimate *= TICKSCALE;
|
|
|
|
MYASSERT (Slice->TicksSoFar * RevisedEstimate > Slice->TicksSoFar);
|
|
MYASSERT (Slice->LastTickDisplayed * RevisedEstimate > Slice->LastTickDisplayed);
|
|
|
|
Slice->TicksSoFar = (UINT) ((LONGLONG) Slice->TicksSoFar * (LONGLONG) RevisedEstimate / (LONGLONG) Slice->TotalTicks);
|
|
Slice->LastTickDisplayed = (UINT) ((LONGLONG) Slice->LastTickDisplayed * (LONGLONG) RevisedEstimate / (LONGLONG) Slice->TotalTicks);
|
|
Slice->TotalTicks = RevisedEstimate;
|
|
}
|
|
|
|
|
|
VOID
|
|
BeginSliceProcessing (
|
|
IN UINT SliceId
|
|
)
|
|
{
|
|
PSLICE Slice;
|
|
UINT u;
|
|
UINT TotalTicks;
|
|
|
|
MYASSERT (g_ProgBarInitialized);
|
|
if (!g_ProgBarInitialized) {
|
|
return;
|
|
}
|
|
|
|
if (!g_ProgressBar) {
|
|
DEBUGMSG ((DBG_WHOOPS, "No progress bar handle"));
|
|
return;
|
|
}
|
|
|
|
if (SliceId >= g_SliceCount) {
|
|
DEBUGMSG ((DBG_WHOOPS, "BeginSliceProcessing: Invalid slice ID %u", SliceId));
|
|
return;
|
|
}
|
|
|
|
if (!g_CurrentTickCount) {
|
|
//
|
|
// Initialize the progress bar
|
|
//
|
|
|
|
MYASSERT (g_CurrentSliceId == (UINT)-1);
|
|
|
|
TotalTicks = 0;
|
|
Slice = (PSLICE) g_SliceArray.Buf;
|
|
|
|
for (u = 0 ; u < g_SliceCount ; u++) {
|
|
TotalTicks += Slice->InitialGuess;
|
|
Slice++;
|
|
}
|
|
|
|
TotalTicks /= TICKSCALE;
|
|
g_PaddingTicks = TotalTicks * 5 / 100;
|
|
g_MaxTickCount = TotalTicks + 2 * g_PaddingTicks;
|
|
|
|
g_ReduceFactor = 1;
|
|
while (g_MaxTickCount > 0xffff) {
|
|
g_ReduceFactor *= 10;
|
|
g_MaxTickCount /= 10;
|
|
}
|
|
|
|
SendMessage (g_ProgressBar, PBM_SETRANGE, 0, MAKELPARAM (0, g_MaxTickCount));
|
|
SendMessage (g_ProgressBar, PBM_SETSTEP, 1, 0);
|
|
|
|
if (g_Reverse) {
|
|
SendMessage (
|
|
g_ProgressBar,
|
|
PBM_SETPOS,
|
|
g_MaxTickCount - (g_PaddingTicks / g_ReduceFactor),
|
|
0
|
|
);
|
|
} else {
|
|
SendMessage (g_ProgressBar, PBM_SETPOS, g_PaddingTicks / g_ReduceFactor, 0);
|
|
}
|
|
|
|
g_CurrentTickCount = g_PaddingTicks;
|
|
g_CurrentPos = g_PaddingTicks;
|
|
|
|
} else if (SliceId <= g_CurrentSliceId) {
|
|
DEBUGMSG ((DBG_WHOOPS, "BeginSliceProcessing: Slice ID %u processed already", SliceId));
|
|
return;
|
|
}
|
|
|
|
|
|
g_CurrentSliceId = SliceId;
|
|
Slice = (PSLICE) g_SliceArray.Buf + g_CurrentSliceId;
|
|
|
|
Slice->Started = TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
pIncrementBarIfNecessary (
|
|
IN OUT PSLICE Slice
|
|
)
|
|
{
|
|
UINT Increment;
|
|
UINT Pos;
|
|
|
|
if (Slice->TicksSoFar >= Slice->TotalTicks) {
|
|
Slice->TicksSoFar = Slice->TotalTicks;
|
|
Slice->Completed = TRUE;
|
|
}
|
|
|
|
if (Slice->TicksSoFar - Slice->LastTickDisplayed >= TICKSCALE) {
|
|
Increment = (Slice->TicksSoFar - Slice->LastTickDisplayed) / TICKSCALE;
|
|
Slice->LastTickDisplayed += Increment * TICKSCALE;
|
|
|
|
if (g_Reverse) {
|
|
|
|
Pos = ((g_CurrentPos + Slice->TicksSoFar) / TICKSCALE);
|
|
|
|
Pos += g_PaddingTicks;
|
|
Pos /= g_ReduceFactor;
|
|
|
|
if (Pos > g_MaxTickCount) {
|
|
Pos = g_MaxTickCount - (g_PaddingTicks / g_ReduceFactor);
|
|
}
|
|
|
|
SendMessage (g_ProgressBar, PBM_SETPOS, g_MaxTickCount - Pos, 0);
|
|
} else {
|
|
SendMessage (g_ProgressBar, PBM_DELTAPOS, Increment / g_ReduceFactor, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
pTickProgressBar (
|
|
IN UINT Ticks
|
|
)
|
|
{
|
|
PSLICE Slice;
|
|
LONGLONG x;
|
|
|
|
if (!Ticks || g_CurrentSliceId == (UINT)-1 || g_CurrentSliceId >= g_SliceCount) {
|
|
return;
|
|
}
|
|
|
|
Slice = (PSLICE) g_SliceArray.Buf + g_CurrentSliceId;
|
|
|
|
if (!Slice->InitialGuess) {
|
|
return;
|
|
}
|
|
|
|
if (Slice->Completed) {
|
|
DEBUGMSG ((DBG_VERBOSE, "Progress slice ID %u already completed", g_CurrentSliceId));
|
|
return;
|
|
}
|
|
|
|
MYASSERT (Ticks * TICKSCALE > Ticks);
|
|
x = ((LONGLONG) Ticks * TICKSCALE * (LONGLONG) Slice->TotalTicks) / (LONGLONG) Slice->InitialGuess;
|
|
MYASSERT (x + (LONGLONG) Slice->TicksSoFar < 0x100000000);
|
|
|
|
Slice->TicksSoFar += (UINT) x;
|
|
|
|
pIncrementBarIfNecessary (Slice);
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
TickProgressBarDelta (
|
|
IN UINT TickCount
|
|
)
|
|
{
|
|
BOOL rSuccess = TRUE;
|
|
|
|
if (!g_ProgBarInitialized) {
|
|
return TRUE;
|
|
}
|
|
|
|
if (g_CancelFlagPtr && *g_CancelFlagPtr) {
|
|
SetLastError (ERROR_CANCELLED);
|
|
rSuccess = FALSE;
|
|
} else {
|
|
pTickProgressBar (TickCount);
|
|
}
|
|
|
|
return rSuccess;
|
|
}
|
|
|
|
|
|
BOOL
|
|
TickProgressBar (
|
|
VOID
|
|
)
|
|
{
|
|
if (!g_ProgBarInitialized) {
|
|
return TRUE;
|
|
}
|
|
|
|
return TickProgressBarDelta (1);
|
|
}
|
|
|
|
|
|
VOID
|
|
EndSliceProcessing (
|
|
VOID
|
|
)
|
|
{
|
|
PSLICE Slice;
|
|
|
|
if (!g_ProgBarInitialized) {
|
|
return;
|
|
}
|
|
|
|
Slice = (PSLICE) g_SliceArray.Buf + g_CurrentSliceId;
|
|
|
|
if (!Slice->InitialGuess) {
|
|
Slice->Completed = TRUE;
|
|
return;
|
|
}
|
|
|
|
if (!Slice->Completed) {
|
|
DEBUGMSG ((DBG_WARNING, "Progress bar slice %u was not completed.", g_CurrentSliceId));
|
|
|
|
Slice->TicksSoFar = Slice->TotalTicks;
|
|
Slice->Completed = TRUE;
|
|
|
|
pIncrementBarIfNecessary (Slice);
|
|
}
|
|
|
|
g_CurrentPos += Slice->TotalTicks;
|
|
|
|
if (g_CurrentSliceId == g_SliceCount - 1) {
|
|
//
|
|
// End of progress bar
|
|
//
|
|
|
|
SendMessage (g_ProgressBar, PBM_SETPOS, g_MaxTickCount, 0);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
pCheckProgressBarState (
|
|
IN HANDLE CancelEvent
|
|
)
|
|
{
|
|
|
|
SetEvent(CancelEvent);
|
|
|
|
return (!g_CancelFlagPtr || !*g_CancelFlagPtr);
|
|
}
|
|
|
|
|
|
BOOL
|
|
ProgressBar_SetWindowStringA(
|
|
IN HWND Window,
|
|
IN HANDLE CancelEvent,
|
|
IN PCSTR Message, OPTIONAL
|
|
IN DWORD MessageId OPTIONAL
|
|
)
|
|
{
|
|
BOOL rSuccess = TRUE;
|
|
PCSTR string = NULL;
|
|
|
|
EnterOurCriticalSection (&g_ProgBarCriticalSection);
|
|
|
|
if (g_ProgBarInitialized) {
|
|
|
|
if (pCheckProgressBarState(CancelEvent)) {
|
|
|
|
if (Message) {
|
|
|
|
//
|
|
// We have a normal message string.
|
|
//
|
|
|
|
if (!SetWindowTextA(Window, Message)) {
|
|
rSuccess = FALSE;
|
|
DEBUGMSG((DBG_ERROR,"ProgressBar: SetWindowText failed."));
|
|
}
|
|
}
|
|
else if (MessageId) {
|
|
|
|
//
|
|
// We have a message ID. Convert it and set it.
|
|
//
|
|
string = GetStringResourceA(MessageId);
|
|
|
|
if (string) {
|
|
|
|
if (!SetWindowTextA(Window, string)) {
|
|
rSuccess = FALSE;
|
|
DEBUGMSG((DBG_ERROR,"ProgressBar: SetWindowText failed."));
|
|
}
|
|
|
|
FreeStringResourceA(string);
|
|
}
|
|
ELSE_DEBUGMSG((DBG_ERROR,"ProgressBar: Error with GetStringResource"));
|
|
|
|
}
|
|
else {
|
|
|
|
//
|
|
// Just clear the text.
|
|
//
|
|
|
|
if (!SetWindowTextA(Window, "")) {
|
|
rSuccess = FALSE;
|
|
DEBUGMSG((DBG_ERROR,"ProgressBar: SetWindowText failed."));
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// We are in a canceled state.
|
|
//
|
|
rSuccess = FALSE;
|
|
SetLastError (ERROR_CANCELLED);
|
|
}
|
|
}
|
|
|
|
LeaveOurCriticalSection (&g_ProgBarCriticalSection);
|
|
|
|
return rSuccess;
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
pSetDelayedMessageA (
|
|
IN PVOID Param
|
|
)
|
|
{
|
|
DWORD rc = ERROR_SUCCESS;
|
|
PDELAYTHREADPARAMS tParams = (PDELAYTHREADPARAMS) Param;
|
|
|
|
//
|
|
// Simply wait for the passed in delay or until someone signals the cancel
|
|
// event.
|
|
//
|
|
switch (WaitForSingleObject(tParams -> CancelEvent, tParams -> Delay)) {
|
|
|
|
case WAIT_TIMEOUT:
|
|
//
|
|
// We timed out without cancel being signaled. Set the delayed message.
|
|
//
|
|
ProgressBar_SetWindowStringA (
|
|
tParams -> Window,
|
|
tParams -> CancelEvent,
|
|
tParams -> Message,
|
|
tParams -> MessageId
|
|
);
|
|
|
|
break;
|
|
|
|
case WAIT_OBJECT_0:
|
|
default:
|
|
//
|
|
// We were canceled (or something strange happened :> Do nothing!
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// can set a new thread now
|
|
//
|
|
tParams->InUse = FALSE;
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
VOID
|
|
ProgressBar_CancelDelayedMessage (
|
|
IN HANDLE CancelEvent
|
|
)
|
|
{
|
|
if (!g_ProgBarInitialized) {
|
|
return;
|
|
}
|
|
|
|
SetEvent(CancelEvent);
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
ProgressBar_SetDelayedMessageA (
|
|
IN HWND Window,
|
|
IN HANDLE CancelEvent,
|
|
IN LPCSTR Message,
|
|
IN DWORD MessageId,
|
|
IN DWORD Delay
|
|
)
|
|
{
|
|
BOOL rSuccess = FALSE;
|
|
DWORD threadId;
|
|
static DELAYTHREADPARAMS tParams;
|
|
|
|
if (!g_ProgBarInitialized || tParams.InUse) {
|
|
return TRUE;
|
|
}
|
|
|
|
if (!pCheckProgressBarState(Window)) {
|
|
|
|
|
|
//
|
|
// Fill in the parameters for this call to create thread.
|
|
//
|
|
tParams.Window = Window;
|
|
tParams.CancelEvent = CancelEvent;
|
|
tParams.Message = Message;
|
|
tParams.MessageId = MessageId;
|
|
tParams.Delay = Delay;
|
|
|
|
//
|
|
// Spawn off a thread that will set the message.
|
|
//
|
|
rSuccess = NULL != CreateThread (
|
|
NULL, // No inheritance.
|
|
0, // Normal stack size.
|
|
pSetDelayedMessageA,
|
|
&tParams,
|
|
0, // Run immediately.
|
|
&threadId
|
|
);
|
|
|
|
if (rSuccess) {
|
|
tParams.InUse = TRUE;
|
|
}
|
|
ELSE_DEBUGMSG((DBG_ERROR,"Error spawning thread in ProgressBar_SetDelayedMessageA."));
|
|
}
|
|
|
|
return rSuccess;
|
|
}
|
|
|
|
#if 0
|
|
|
|
DWORD
|
|
pTickProgressBarThread (
|
|
IN PVOID Param
|
|
)
|
|
{
|
|
DWORD rc = ERROR_SUCCESS;
|
|
PTICKTHREADPARAMS Params = (PTICKTHREADPARAMS)Param;
|
|
BOOL Continue = TRUE;
|
|
|
|
//
|
|
// Simply wait for the passed in delay or until someone signals the cancel
|
|
// event.
|
|
//
|
|
|
|
do {
|
|
switch (WaitForSingleObject(Params->CancelEvent, Params->TickCount)) {
|
|
|
|
case WAIT_TIMEOUT:
|
|
//
|
|
// We timed out without cancel being signaled. Tick the progress bar.
|
|
//
|
|
if (!TickProgressBarDelta (Params->TickCount)) {
|
|
//
|
|
// cancelled
|
|
//
|
|
Continue = FALSE;
|
|
}
|
|
break;
|
|
|
|
case WAIT_OBJECT_0:
|
|
default:
|
|
//
|
|
// We were canceled (or something strange happened :> Do nothing!
|
|
//
|
|
Continue = FALSE;
|
|
break;
|
|
}
|
|
} while (Continue);
|
|
|
|
//
|
|
// can set a new thread now
|
|
//
|
|
Params->InUse = FALSE;
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ProgressBar_CreateTickThread (
|
|
IN HANDLE CancelEvent,
|
|
IN DWORD TickCount
|
|
)
|
|
{
|
|
BOOL rSuccess = FALSE;
|
|
DWORD threadId;
|
|
static TICKTHREADPARAMS g_Params;
|
|
|
|
if (g_ProgBarInitialized && !g_Params.InUse) {
|
|
|
|
if (pCheckProgressBarState(NULL)) {
|
|
|
|
//
|
|
// Fill in the parameters for this call to create thread.
|
|
//
|
|
g_Params.CancelEvent = CancelEvent;
|
|
g_Params.TickCount = TickCount;
|
|
|
|
//
|
|
// Spawn off a thread that will set the message.
|
|
//
|
|
if (CreateThread (
|
|
NULL, // No inheritance.
|
|
0, // Normal stack size.
|
|
pTickProgressBarThread,
|
|
&g_Params,
|
|
0, // Run immediately.
|
|
&threadId
|
|
)) {
|
|
rSuccess = TRUE;
|
|
g_Params.InUse = TRUE;
|
|
}
|
|
ELSE_DEBUGMSG ((DBG_ERROR, "Error spawning thread in ProgressBar_CreateTickThread."));
|
|
}
|
|
}
|
|
|
|
return rSuccess;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ProgressBar_CancelTickThread (
|
|
IN HANDLE CancelEvent
|
|
)
|
|
{
|
|
if (!g_ProgBarInitialized) {
|
|
return TRUE;
|
|
}
|
|
|
|
return SetEvent(CancelEvent);
|
|
}
|
|
|
|
#endif
|