Files
Hellfire/Uisrc/UI/PROGRESS.CPP
T
Justin Marshall 7806bb8ef8 Added uisrc.
2026-04-27 10:37:37 -07:00

351 lines
8.3 KiB
C++

//****************************************************************************
// Progress.cpp
// Diablo UI progress bar popup dialog
//
// By Frank Pearce
// created 9.26.96
//****************************************************************************
#include "pch.h"
//****************************************************************************
//****************************************************************************
#define PROGRESS_TIMER_ID 1
#define MILLISEC_PER_SEC 1000
#define CALLS_PER_SEC 20
#define USER_DELAY (MILLISEC_PER_SEC / sgCallsPerSec)
#define DEFAULT_DELAY (MILLISEC_PER_SEC / CALLS_PER_SEC)
#define FILL_X 0
#define FILL_Y 0
static LPBYTE sgBgBmp = NULL;
static LPBYTE sgBtnBmp = NULL;
// the progress bar background
static LPBYTE sgProgBgBmp = NULL;
static SIZE sgProgBgSize;
// the fill image for the progress bar
static LPBYTE sgProgFillBmp = NULL;
static SIZE sgProgFillSize;
// the current image based on percent complete
static LPBYTE sgProgBmp = NULL;
static SIZE sgProgSize;
static BOOL sgAbortable;
static DWORD sgCallsPerSec;
static PROGRESSFCN sgProgressFcn;
static int sgnResult;
static BOOL sgbEndDialog;
//****************************************************************************
//****************************************************************************
static void ProgressDraw(HWND window, int percent) {
RECT rect;
HWND child = GetDlgItem(window, IDC_UIGENERIC_PROGRESS);
// draw the bg
if (sgProgBgBmp)
SBltROP3(
sgProgBmp,
sgProgBgBmp,
sgProgSize.cx,
sgProgSize.cy,
sgProgSize.cx,
sgProgBgSize.cx,
NULL,
SRCCOPY
);
// draw the fill
if (sgProgFillBmp)
SBltROP3(
sgProgBmp + (FILL_Y * sgProgSize.cx) + FILL_X,
sgProgFillBmp,
((sgProgSize.cx - (2 * FILL_X)) * percent) / 100,
sgProgSize.cy - (2 * FILL_Y),
sgProgSize.cx,
sgProgFillSize.cx,
NULL,
SRCCOPY
);
// invalidate the region
GetWindowRect(child, &rect);
ScreenToClient(window, (LPPOINT)&rect.left);
ScreenToClient(window, (LPPOINT)&rect.right);
InvalidateRect(window, &rect, FALSE);
}
//****************************************************************************
//****************************************************************************
static void ProgressDestroy(HWND window) {
if (sgBgBmp) {
FREE(sgBgBmp);
sgBgBmp = NULL;
}
if (sgBtnBmp) {
FREE(sgBtnBmp);
sgBtnBmp = NULL;
}
if (sgProgBgBmp) {
FREE(sgProgBgBmp);
sgProgBgBmp = NULL;
}
if (sgProgFillBmp) {
FREE(sgProgFillBmp);
sgProgFillBmp = NULL;
}
if (sgProgBmp) {
FREE(sgProgBmp);
sgProgBmp = NULL;
}
}
//****************************************************************************
//****************************************************************************
static void ProgressInit(HWND window, LPCSTR progresstext) {
PALETTEENTRY * pal;
HWND child;
RECT rect;
SIZE btnsize;
int BtnIDs[] = { IDCANCEL, 0 };
if (sgCallsPerSec)
SDlgSetTimer(window,PROGRESS_TIMER_ID,USER_DELAY,NULL);
else
SDlgSetTimer(window,PROGRESS_TIMER_ID,DEFAULT_DELAY,NULL);
// load ctrl/dlg bmps
LoadArtFile(
window,
NULL,
TEXT(""),
SDLG_STYLE_ANY,
SDLG_USAGE_BACKGROUND,
TEXT("ui_art\\spopup.pcx"),
&sgBgBmp,
NULL,
FALSE
);
if (SDrawGetFrameWindow() == GetParent(window))
UiAltFadeInit(window);
// load just the part of the palette the dialog uses
pal = UiPaletteEntry(0);
SDrawUpdatePalette(0, 10, &pal[0]); // Windows colors also
SDrawUpdatePalette(0x70, 144, &pal[0x70], TRUE);
UiLoadBmpFile(
TEXT("ui_art\\but_sml.pcx"),
&sgBtnBmp,
&btnsize
);
if (sgBtnBmp)
UiSetButtonBitmaps(window, BtnIDs, sgBtnBmp, &btnsize);
// load progress bar textures
UiLoadBmpFile(
TEXT("ui_art\\prog_bg.pcx"),
&sgProgBgBmp,
&sgProgBgSize
);
UiLoadBmpFile(
TEXT("ui_art\\prog_fil.pcx"),
&sgProgFillBmp,
&sgProgFillSize
);
// alloc/create a bitmap for the progress indicator
child = GetDlgItem(window, IDC_UIGENERIC_PROGRESS);
GetClientRect(child, &rect);
sgProgBmp = (LPBYTE) ALLOC(rect.right * rect.bottom);
if (!sgProgBmp)
return;
sgProgSize.cx = rect.right;
sgProgSize.cy = rect.bottom;
SDlgSetBitmap(
child,
NULL,
NULL,
SDLG_STYLE_ANY,
SDLG_USAGE_BACKGROUND,
sgProgBmp,
NULL,
rect.right,
rect.bottom
);
ProgressDraw(window, 0);
// set the text describing what progress is being monitored
child = GetDlgItem(window, IDC_PROGRESS_TEXT);
SetWindowText(child, progresstext);
// show/hide cancel button based on abortable flag
child = GetDlgItem(window, IDCANCEL);
ShowWindow(child, (sgAbortable ? SW_SHOWNORMAL : SW_HIDE));
EnableWindow(child, sgAbortable);
}
//****************************************************************************
//****************************************************************************
static void ProgressEndDialog(HWND window, int nResult) {
sgnResult = IDCANCEL;
sgbEndDialog = TRUE;
}
//****************************************************************************
//****************************************************************************
static void ProgressAbort(HWND window) {
SDlgKillTimer(window, PROGRESS_TIMER_ID);
if (SDrawGetFrameWindow() == GetParent(window))
UiVidFadeOut(DEFAULT_STEPS*2);
ProgressEndDialog(window, 0);
sgnResult = 0;
}
//****************************************************************************
//****************************************************************************
static void ProgressTimer(HWND window) {
int percent;
percent = sgProgressFcn();
if (percent >= 100) {
ProgressAbort(window);
}
else {
ProgressDraw(window, percent);
}
}
//****************************************************************************
//****************************************************************************
static BOOL CALLBACK ProgressDialogProc (HWND window,
UINT message,
WPARAM wparam,
LPARAM lparam) {
switch (message) {
case WM_COMMAND:
if (LOWORD(wparam) == IDCANCEL) {
SDlgKillTimer(window, PROGRESS_TIMER_ID);
if (SDrawGetFrameWindow() == GetParent(window))
UiVidFadeOut(DEFAULT_STEPS*2);
ProgressEndDialog(window, IDCANCEL);
}
break;
case WM_DESTROY:
ShowCursor(FALSE);
ProgressDestroy(window);
break;
case WM_INITDIALOG:
ProgressInit(window, (LPCSTR)lparam);
// Choose our cursors
UiSetWindowsCursors(SDrawGetFrameWindow());
UiSetWindowsCursors(window);
ShowCursor(TRUE);
return 1;
case WM_TIMER:
ProgressTimer(window);
break;
case WM_SYSKEYUP:
case WM_SYSKEYDOWN:
SendMessage(SDrawGetFrameWindow(), message, wparam, lparam);
break;
}
return SDlgDefDialogProc(window,message,wparam,lparam);
}
//****************************************************************************
//****************************************************************************
static void ProcessMessages(HWND hWnd) {
while (IsWindow(hWnd) && !sgbEndDialog) {
MSG message;
if (PeekMessage(&message,(HWND)0,0,0,PM_REMOVE)) {
if (message.message == WM_QUIT)
PostQuitMessage(message.wParam);
else if (!IsDialogMessage(hWnd,&message)) {
TranslateMessage(&message);
DispatchMessage(&message);
}
}
else {
SDlgCheckTimers();
SDlgUpdateCursor();
}
}
// Get rid of the window if it is killing itself
if (sgbEndDialog) {
DestroyWindow(hWnd);
sgbEndDialog = FALSE;
}
}
//****************************************************************************
//*
//* EXPORTED FUNCTIONS
//*
//****************************************************************************
//****************************************************************************
//****************************************************************************
BOOL APIENTRY UiProgressDialog(HWND parent,
LPCSTR progresstext,
BOOL abortable,
PROGRESSFCN progressfcn,
DWORD callspersec
) {
sgProgressFcn = progressfcn;
sgAbortable = abortable;
sgCallsPerSec = callspersec;
sgnResult = -1;
sgbEndDialog = FALSE;
HWND hWndProgress = SDlgCreateDialogParam(
global_hinstance,
TEXT("PROGRESS_DIALOG"),
parent,
ProgressDialogProc,
(LPARAM) progresstext
);
if (!hWndProgress)
return FALSE;
// Now process messages until dialog exits
// (that way we'll behave modal to the outside world of Diablo.exe)
ProcessMessages(hWndProgress);
if (sgnResult == IDCANCEL || sgnResult == -1)
return FALSE;
return TRUE;
}