From b77ca97431bb0b1fb15d683b39a39ac395083a5d Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 22 May 2010 13:42:13 +0200 Subject: [PATCH] Fixed: #869 Crash when updating Windows 7 progress bar --- code/nel/include/nel/misc/system_utils.h | 51 ++++++++++++ code/nel/src/misc.vcproj | 8 ++ code/nel/src/misc/system_utils.cpp | 98 ++++++++++++++++++++++++ code/ryzom/client/src/init.cpp | 5 ++ code/ryzom/client/src/progress.cpp | 42 +++------- 5 files changed, 174 insertions(+), 30 deletions(-) create mode 100644 code/nel/include/nel/misc/system_utils.h create mode 100644 code/nel/src/misc/system_utils.cpp diff --git a/code/nel/include/nel/misc/system_utils.h b/code/nel/include/nel/misc/system_utils.h new file mode 100644 index 000000000..b0a0f66bd --- /dev/null +++ b/code/nel/include/nel/misc/system_utils.h @@ -0,0 +1,51 @@ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef NL_SYSTEM_UTILS_H +#define NL_SYSTEM_UTILS_H + +#include "types_nl.h" +#include "ucstring.h" + +namespace NLMISC +{ + +/* + * Operating system miscellaneous functions (all methods and variables should be static) + * \author Kervala + * \date 2010 + */ +class CSystemUtils +{ + static void *s_window; +public: + + /// Initialize data which needs it before using them. + static bool init(); + + /// Uninitialize data when they won't be used anymore. + static bool uninit(); + + /// Set the window which will be used by some functions. + static void setWindow(void *window); + + /// Create/update a progress bar with an appearance depending on system. + static bool updateProgressBar(uint value, uint total); +}; + +} // NLMISC + +#endif // NL_SYSTEM_UTILS_H diff --git a/code/nel/src/misc.vcproj b/code/nel/src/misc.vcproj index 6d198195d..36c0efdfd 100644 --- a/code/nel/src/misc.vcproj +++ b/code/nel/src/misc.vcproj @@ -1541,6 +1541,14 @@ RelativePath="..\include\nel\misc\inter_window_msg_queue.h" > + + + + diff --git a/code/nel/src/misc/system_utils.cpp b/code/nel/src/misc/system_utils.cpp new file mode 100644 index 000000000..8a4e5161a --- /dev/null +++ b/code/nel/src/misc/system_utils.cpp @@ -0,0 +1,98 @@ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdmisc.h" +#include "nel/misc/system_utils.h" + +#ifdef NL_OS_WINDOWS + #define NOMINMAX + #include + + #ifdef _WIN32_WINNT_WIN7 + // only supported by Windows 7 Platform SDK + #include + #define TASKBAR_PROGRESS 1 + #endif +#endif + +using namespace std; + +namespace NLMISC { + +void *CSystemUtils::s_window = NULL; + +bool CSystemUtils::init() +{ +#ifdef NL_OS_WINDOWS + // initialize COM + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + if (FAILED(hr)) return false; +#endif + + return true; +} + +bool CSystemUtils::uninit() +{ +#ifdef NL_OS_WINDOWS + // uninitialize COM + CoUninitialize(); +#endif + + return true; +} + +void CSystemUtils::setWindow(void *window) +{ + s_window = window; +} + +bool CSystemUtils::updateProgressBar(uint value, uint total) +{ +#ifdef TASKBAR_PROGRESS + if (s_window == NULL) + { + nlwarning("No window has be set with CSystemUtils::setWindow(), progress bar can't be displayed"); + return false; + } + + ITaskbarList3 *pTaskbarList = NULL; + + // instanciate the taskbar control COM object + HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pTaskbarList)); + // error can be ignored because Windows versions before Windows 7 doesn't support it + if (FAILED(hr) || !pTaskbarList) return false; + + if (total) + { + // update the taskbar progress + hr = pTaskbarList->SetProgressValue((HWND)s_window, (ULONGLONG)value, (ULONGLONG)total); + } + else + { + // don't update anymore the progress + hr = pTaskbarList->SetProgressState((HWND)s_window, value == 0 ? TBPF_INDETERMINATE:TBPF_NOPROGRESS); + } + + // release the interface + pTaskbarList->Release(); + +#endif // TASKBAR_PROGRESS + + return true; +} + +} // NLMISC diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index 721897fda..a41dfca1f 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -33,6 +33,7 @@ #include "nel/misc/class_registry.h" #include "nel/misc/system_info.h" #include "nel/misc/block_memory.h" +#include "nel/misc/system_utils.h" // 3D Interface. #include "nel/3d/bloom_effect.h" #include "nel/3d/u_driver.h" @@ -899,6 +900,10 @@ void prelogInit() return; } + // initialize system utils class + CSystemUtils::init(); + CSystemUtils::setWindow(Driver->getDisplay()); + CLoginProgressPostThread::getInstance().step(CLoginStep(LoginStep_VideoModeSetupHighColor, "login_step_video_mode_setup_high_color")); #ifdef NL_OS_WINDOWS diff --git a/code/ryzom/client/src/progress.cpp b/code/ryzom/client/src/progress.cpp index 72274785f..e3c4b706b 100644 --- a/code/ryzom/client/src/progress.cpp +++ b/code/ryzom/client/src/progress.cpp @@ -23,11 +23,6 @@ #include "nel/3d/u_texture.h" #include "game_share/ryzom_version.h" #include "nel/misc/i18n.h" -#if defined(NL_OS_WINDOWS) && defined(_WIN32_WINNT_WIN7) - // only supported by Windows 7 Platform SDK - #include - #define TASKBAR_PROGRESS 1 -#endif #include "continent.h" #include "weather.h" #include "weather_manager_client.h" @@ -37,6 +32,7 @@ #include "client_cfg.h" #include "interface_v3/custom_mouse.h" #include "bg_downloader_access.h" +#include "nel/misc/system_utils.h" using namespace std; using namespace NLMISC; @@ -52,10 +48,6 @@ extern uint TipsOfTheDayIndex; extern ucstring TipsOfTheDay; extern bool UseEscapeDuringLoading; -#ifdef TASKBAR_PROGRESS - static ITaskbarList3* pTaskbarList = NULL; -#endif - CProgress::CProgress () { _LastUpdate = ryzomGetLocalTime (); @@ -63,22 +55,10 @@ CProgress::CProgress () pushCropedValues (0, 1); ApplyTextCommands = false; _TPCancelFlag = false; - -#ifdef TASKBAR_PROGRESS - HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); - - // instanciate the taskbar control COM object -// if (SUCCEEDED(hr)) CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pTaskbarList)); -#endif // TASKBAR_PROGRESS } CProgress::~CProgress () { -#ifdef TASKBAR_PROGRESS - if (pTaskbarList) pTaskbarList->Release(); - - CoUninitialize(); -#endif // TASKBAR_PROGRESS } void CProgress::setFontFactor(float temp) @@ -394,10 +374,15 @@ void CProgress::internalProgress (float value) CCDBNodeBranch::flushObserversCalls(); //CustomMouse.updateCursor(); -#ifdef TASKBAR_PROGRESS - // update the taskbar progress - if (pTaskbarList) pTaskbarList->SetProgressValue((HWND)Driver->getDisplay(), ULONGLONG(value * 1000), 1000); -#endif // TASKBAR_PROGRESS + // update system dependent progress bar + static uint previousValue = 0; + uint currentValue = (uint)(value*100.0f); + + if (currentValue != previousValue) + { + CSystemUtils::updateProgressBar(currentValue, 100); + previousValue = currentValue; + } } @@ -430,9 +415,6 @@ void CProgress::release() void CProgress::finish() { -#ifdef TASKBAR_PROGRESS - // don't update anymore the progress - if (pTaskbarList && Driver) pTaskbarList->SetProgressState((HWND)Driver->getDisplay(), TBPF_NOPROGRESS); -#endif // TASKBAR_PROGRESS + // stop system dependent progress bar + CSystemUtils::updateProgressBar(1, 0); } -