#include "Install.h" #include ////////////////////////////////////////////////////////////////////// ProgressMeter::ProgressMeter(int chunk, const char *text, int total, int flags, HWND parent) : chunk(chunk) , text(text) , total(total) , parent(parent) , flags(flags) , window(0) , pos(0) , cancel(false) , caption("Working...") , next_ticks(0) { } ////////////////////////////////////////////////////////////////////// ProgressMeter::ProgressMeter(const char *title, int step, int total, int flags, HWND parent) : chunk(step) , text(title) , total(total) , parent(parent) , flags(flags) , window(0) , pos(0) , cancel(false) , caption("Working...") , next_ticks(0) { } ////////////////////////////////////////////////////////////////////// ProgressMeter::~ProgressMeter() { Destroy(); } ////////////////////////////////////////////////////////////////////// LRESULT CALLBACK ProgressMeter::StaticProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { if(message == WM_CREATE) { CREATESTRUCT *pp = (CREATESTRUCT *)lParam; ASSERT(pp -> lpCreateParams); SetWindowLong(hwnd, GWL_USERDATA, (long)pp -> lpCreateParams); ((ProgressMeter *)pp -> lpCreateParams) -> window = hwnd; } ProgressMeter *pp = (ProgressMeter *)GetWindowLong(hwnd, GWL_USERDATA); if(pp) return pp -> Proc(message, wParam, lParam); else return DefWindowProc(hwnd, message, wParam, lParam); } ////////////////////////////////////////////////////////////////////// LRESULT ProgressMeter::Proc(UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_CREATE: cancel = false; break; case WM_KEYDOWN: if(IsAllowCancel() && wParam == VK_ESCAPE) { cancel = true; Destroy(); return 0; } break; case WM_COMMAND: if(IsAllowCancel() && LOWORD(wParam) == IDCANCEL) { cancel = true; Destroy(); } return 0; case WM_CLOSE: if(IsAllowCancel()) { cancel = true; Destroy(); } return 0; } return DefWindowProc(window, message, wParam, lParam); } ////////////////////////////////////////////////////////////////////// ProgressMeter& ProgressMeter::Caption(const char *_caption) { if(caption != _caption) { caption = _caption; if(IsOpen()) SetWindowText(window, caption); } return *this; } ////////////////////////////////////////////////////////////////////// bool ProgressMeter::Create() { if(window) return true; if(cancel) return false; // if(AfxGetApp()) // AfxGetApp() -> BeginWaitCursor(); HINSTANCE instance = AppGetHandle(); dword process = GetCurrentProcessId(); static const char classname[] = "Cybex_Progress"; static bool done = false; if(!done) { done = true; WNDCLASS wndclass = { CS_DBLCLKS | CS_SAVEBITS, // UINT style; StaticProc, // WNDPROC lpfnWndProc; 0, // int cbClsExtra; 0, // int cbWndExtra; instance, // HANDLE hInstance; 0, // HICON hIcon; LoadCursor(0, IDC_WAIT), // HCURSOR hCursor; GetSysColorBrush(COLOR_BTNFACE), // HBRUSH hbrBackground; NULL, // LPCTSTR lpszMenuName; classname, // LPCTSTR lpszClassName; }; RegisterClass(&wndclass); } enum { CXWND = 240, CYWND = 70, CXGAP = 5, CYGAP = 5, XPROGRESS = CXGAP, CXPROGRESS = CXWND - 2 * XPROGRESS, CYPROGRESS = 10, YPROGRESS = (CYWND - CYPROGRESS - 10) >> 1, XTEXT = CXGAP, YTEXT = CYGAP, CXTEXT = CXWND - 2 * XTEXT, CYTEXT = YPROGRESS - YTEXT, CXBUTTON = 60, CYBUTTON = 22, XBUTTON = (CXWND - CXBUTTON) >> 1, YBUTTON = CYWND - CYGAP - CYBUTTON, STYLE = WS_OVERLAPPED | WS_DLGFRAME | WS_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN, }; Size screen(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); if(parent) while(GetParent(parent)) parent = GetParent(parent); if(!parent) { if(parent = GetActiveWindow()) while(GetParent(parent)) parent = GetParent(parent); if(parent && !(IsWindowVisible(parent) && IsWindowEnabled(parent))) parent = 0; } if(parent) enable.Add(parent); //* for(HWND hwnd = GetWindow(GetDesktopWindow(), GW_CHILD); hwnd; hwnd = GetWindow(hwnd, GW_HWNDNEXT)) { dword wprocess; GetWindowThreadProcessId(hwnd, &wprocess); if(wprocess == process && IsWindowVisible(hwnd) && IsWindowEnabled(hwnd)) enable.Add(hwnd); } if(!parent && !enable.IsEmpty()) parent = enable[0]; //*/ if(!parent) parent = GetDesktopWindow(); Rect pane(0, 0, CXWND, CYWND); AdjustWindowRect(pane, STYLE, false); pane.Offset((screen >> 1) - pane.CenterPoint()); CreateWindowEx( WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE, classname, caption, STYLE, pane.left, pane.top, pane.Width(), pane.Height(), parent, 0, instance, this); if(!window) return false; SendMessage(window, WM_SETICON, ICON_BIG, 0); SendMessage(window, WM_SETICON, ICON_SMALL, 0); VERIFY(CreateWindow("static", NULL, WS_CHILD | WS_VISIBLE | SS_CENTER | SS_NOPREFIX, XTEXT, YTEXT, CXTEXT, CYTEXT, window, (HMENU)IDOK, instance, 0)); // INITCOMMONCONTROLSEX icc; // icc.dwSize = sizeof(icc); // icc.dwICC = ICC_PROGRESS_CLASS; // InitCommonControlsEx(&icc); InitCommonControls(); VERIFY(progress = CreateWindow("msctls_progress32", NULL, WS_CHILD | WS_DISABLED | (total ? WS_VISIBLE : 0), XPROGRESS, YPROGRESS, CXPROGRESS, CYPROGRESS, window, 0, instance, 0)); VERIFY(CreateWindow("button", "Cancel", (flags & NOCANCEL ? 0 : WS_VISIBLE) | WS_CHILD | BS_PUSHBUTTON, XBUTTON, YBUTTON, CXBUTTON, CYBUTTON, window, (HMENU)IDCANCEL, instance, 0)); HFONT font = (HFONT)GetStockObject(ANSI_VAR_FONT); SendDlgItemMessage(window, IDOK, WM_SETFONT, (WPARAM)font, true); SendDlgItemMessage(window, IDCANCEL, WM_SETFONT, (WPARAM)font, true); ShowWindow(window, SW_SHOW); Enable(false); old_text = Null; Set(pos, total); return true; } ////////////////////////////////////////////////////////////////////// ProgressMeter& ProgressMeter::SetText(const char *s, bool reset) { if(reset) Reset(); text = s; return Set(pos, total); } ////////////////////////////////////////////////////////////////////// ProgressMeter& ProgressMeter::Set(int apos, int atotal) { if(cancel && flags & THROW) throw AbortExc(); if(atotal >= 0) total = atotal; if(apos >= 0) pos = apos; if(IgnoreStep(apos)) return *this; next_ticks = GetTickCount() + 500; if(!Create()) return *this; String new_text = Format(text, pos); if(new_text.Compare(old_text)) SetDlgItemText(window, IDOK, old_text = new_text); atotal = total; apos = pos; while(atotal > 30000) { atotal >>= 8; apos >>= 8; } ShowWindow(progress, atotal > 0 ? SW_SHOW : SW_HIDE); if(atotal > 0) { SendMessage(progress, PBM_SETRANGE, 0, MAKELPARAM(0, atotal)); SendMessage(progress, PBM_SETPOS, apos, 0); } return *this; } ////////////////////////////////////////////////////////////////////// ProgressMeter& ProgressMeter::Step() { return Set(++pos, total); } ////////////////////////////////////////////////////////////////////// ProgressMeter& ProgressMeter::SetRange(int atotal) { return Set(pos, atotal); } ////////////////////////////////////////////////////////////////////// ProgressMeter& ProgressMeter::SetPos(int apos) { return Set(apos, total); } ////////////////////////////////////////////////////////////////////// bool ProgressMeter::Cancelled() { Create(); MSG msg; while(::PeekMessage(&msg, flags & FILTER ? window : 0, 0, 0, PM_REMOVE)) ::DispatchMessage(&msg); if(cancel && flags & THROW) throw AbortExc(); return cancel; } ////////////////////////////////////////////////////////////////////// bool ProgressMeter::StepCancelled() { SetPos(pos + 1); return IgnoreStep(pos) ? cancel : Cancelled(); } ////////////////////////////////////////////////////////////////////// bool ProgressMeter::SetPosCancelled(int apos) { SetPos(apos); return IgnoreStep(apos) ? cancel : Cancelled(); } ////////////////////////////////////////////////////////////////////// bool ProgressMeter::IgnoreStep(int pos) const { return (int)GetTickCount() < next_ticks && pos % (chunk ? chunk : 1); } ////////////////////////////////////////////////////////////////////// bool ProgressMeter::OnStep(int apos, int atotal) { if(atotal >= 0) total = atotal; SetPos(apos); return IgnoreStep(apos) ? cancel : Cancelled(); } ////////////////////////////////////////////////////////////////////// void ProgressMeter::Destroy() { if(window) { Enable(true); if(!enable.IsEmpty()) SetActiveWindow(enable[0]); enable.Clear(); DestroyWindow(window); window = NULL; progress = NULL; // if(AfxGetApp()) // AfxGetApp() -> EndWaitCursor(); } } ////////////////////////////////////////////////////////////////////// void ProgressMeter::Enable(bool en) { for(const HWND *p = enable.Begin(), *e = enable.End(); p < e; p++) EnableWindow(*p, en); } ////////////////////////////////////////////////////////////////////// ProgressMeter& ProgressMeter::Filter(bool _fm) { flags = _fm ? flags | FILTER : flags & ~FILTER; return *this; } ////////////////////////////////////////////////////////////////////// ProgressMeter& ProgressMeter::Throw(bool _throw) { flags = _throw ? flags | THROW : flags & ~THROW; return *this; } ////////////////////////////////////////////////////////////////////// ProgressMeter& ProgressMeter::AllowCancel(bool _ac) { flags = _ac ? flags & ~NOCANCEL : flags | NOCANCEL; if(window) ShowWindow(GetDlgItem(window, IDCANCEL), _ac ? SW_SHOW : SW_HIDE); return *this; } ////////////////////////////////////////////////////////////////////// ProgressMeter& ProgressMeter::Show(bool _show) { flags = _show ? flags & ~HIDDEN : flags | HIDDEN; if(window) ShowWindow(window, _show ? SW_SHOW : SW_HIDE); return *this; } //////////////////////////////////////////////////////////////////////