/************************************************************************ MeOS - Orienteering Software Copyright (C) 2009-2024 Melin Software HB This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Melin Software HB - software@melin.nu - www.melin.nu Eksoppsvägen 16, SE-75646 UPPSALA, Sweden ************************************************************************/ #include "stdafx.h" #include #include "oEvent.h" #include "xmlparser.h" #include #include "gdioutput.h" #include "commctrl.h" #include "localizer.h" #include "progress.h" void start_progress_thread(void *ptr) { ProgressWindow *pw=(ProgressWindow *)ptr; pw->process(); } const int p_width = 230; const int p_height = 12; ProgressWindow::ProgressWindow(HWND hWndParent) { lastPrg = 0; initialized = false; subStart = 0; subEnd = 1000; hWnd = hWndParent; terminate = false; running = false; } void ProgressWindow::init() { initialized = true; progress = 0; lastProgress = 0; time = 0; lastTime = 0; speed = 0; RECT rc; GetClientRect(hWnd, &rc); hWnd=CreateWindowEx(WS_EX_TOPMOST, L"STATIC", L"", WS_VISIBLE|WS_CHILD, (rc.right-p_width)/2, rc.bottom/2, p_width, p_height+1, hWnd, NULL, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), NULL); ShowWindow(hWnd, SW_SHOW); SetWindowPos(hWnd, HWND_TOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE); SetActiveWindow(hWnd); UpdateWindow(hWnd); InitializeCriticalSection(&syncObj); thread = (HANDLE)_beginthread(start_progress_thread, 0, this); } ProgressWindow::~ProgressWindow() { if (initialized) { setProgress(1000); EnterCriticalSection(&syncObj); terminate = true; LeaveCriticalSection(&syncObj); int maxCount = 100; while (maxCount-- > 0 && running) { Sleep(20); } EnterCriticalSection(&syncObj); if (running) TerminateThread(thread, 0); LeaveCriticalSection(&syncObj); // CloseHandle(thread); DeleteCriticalSection(&syncObj); DestroyWindow(hWnd); } } void ProgressWindow::process() { running = true; while (!terminate) { EnterCriticalSection(&syncObj); if (!terminate) draw(GetTickCount()/40); LeaveCriticalSection(&syncObj); if (!terminate) Sleep(33); } running = false; } void ProgressWindow::draw(int count) { HDC hDC = GetDC(hWnd); int prgBase = getProgress(); int prg = min((prgBase * p_width)/1000, p_width-1); int center = int(prg*((cos(count*0.1)+1)*0.8) / 2); DWORD c=GetSysColor(COLOR_ACTIVECAPTION); double red=GetRValue(c); double green=GetGValue(c); double blue=GetBValue(c); double blue1=min(255., blue*1.4); double green1=min(255., green*1.4); double red1=min(255., red*1.4); int blueD=int(blue/2); int redD=int(red/2); int greenD=int(green/2); SelectObject(hDC, GetStockObject(DC_PEN)); SelectObject(hDC, GetStockObject(NULL_BRUSH)); SetDCPenColor(hDC, RGB(redD,greenD,blueD)); Rectangle(hDC, 0, 0, p_width, p_height-1); SelectObject(hDC, GetStockObject(DC_BRUSH)); SelectObject(hDC, GetStockObject(NULL_PEN)); SetDCBrushColor(hDC, GetSysColor(COLOR_3DHIGHLIGHT)); Rectangle(hDC, prg, 1, p_width-1, p_height-2); TRIVERTEX vert[4]; vert [0] .x = 1; vert [0] .y = 1; vert [0] .Red = 0xff00&DWORD(red*256); vert [0] .Green = 0xff00&DWORD(green*256); vert [0] .Blue = 0xff00&DWORD(blue*256); vert [0] .Alpha = 0x0000; vert [1] .x = center; vert [1] .y = p_height-2; vert [1] .Red = 0xff00&DWORD(red1*256); vert [1] .Green = 0xff00&DWORD(green1*256); vert [1] .Blue = 0xff00&DWORD(blue1*256); vert [1] .Alpha = 0x0000; vert [2] .x = center; vert [2] .y = 1; vert [2] .Red = 0xff00&DWORD(red1*256); vert [2] .Green = 0xff00&DWORD(green1*256); vert [2] .Blue = 0xff00&DWORD(blue1*256); vert [2] .Alpha = 0x0000; vert [3] .x = prg; vert [3] .y = p_height-2; vert [3] .Red = 0xff00&DWORD(red*256); vert [3] .Green = 0xff00&DWORD(green*256); vert [3] .Blue = 0xff00&DWORD(blue*256); vert [3] .Alpha = 0x0000; GRADIENT_RECT gr[2]; gr[0].UpperLeft=0; gr[0].LowerRight=1; gr[1].UpperLeft=2; gr[1].LowerRight=3; GradientFill(hDC,vert, 4, gr, 2, GRADIENT_FILL_RECT_H); ReleaseDC(hWnd, hDC); } int ProgressWindow::getProgress() const { DWORD now = GetTickCount(); int dt = int(now-time); EnterCriticalSection(&syncObj); int dp = int(dt * speed); dp = min(dp, int(progress - lastProgress)); LeaveCriticalSection(&syncObj); return min(progress + dp, 1000); } void ProgressWindow::setProgress(int prg) { if (prg <= lastPrg + 1) return; lastPrg = prg; if (!initialized) return; EnterCriticalSection(&syncObj); lastProgress = progress; lastTime = time; time = GetTickCount(); int newProgress = getProgress(); newProgress = prg > newProgress ? prg : newProgress; if (lastTime>0) speed = double(prg - lastProgress) / double(time-lastTime); progress = max(newProgress, int(progress)); LeaveCriticalSection(&syncObj); } void ProgressWindow::setSubProgress(int prg) { prg = subStart + prg *(subEnd-subStart) / 1000; setProgress(prg); } void ProgressWindow::initSubProgress(int start, int end) { subStart = start; subEnd = end; }