diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 9f85bed459..8444881f68 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1735,7 +1735,6 @@ DoubleChallengeMeter=Double Challenge Meter [StepMania] Announcer=Announcer -Couldn't open any loading windows.=Couldn't open any loading windows. Fullscreen=Fullscreen Initializing %s...=Initializing %s... No video renderers attempted.=No video renderers attempted. @@ -1752,6 +1751,22 @@ Windowed=Windowed color=color texture=texture +[LoadingWindow] +Couldn't open any loading windows.=Couldn't open any loading windows. +Starting sound subsystem...=Starting sound subsystem... +Initializing bookkeeper...=Initializing bookkeeper... +Starting lights subsystem...=Starting lights subsystem... +Loading game type...=Loading game type... +Building song cache index...=Building song cache index... +Loading banner cache...=Loading banner cache... +Initializing memory card system...=Initializing memory card system... +Initializing character system...=Initializing character system... +Initializing profile system...=Initializing profile system... +Updating popular song list...=Updating popular song list... +Updating course rankings...=Updating course rankings... +Initializing statics manager...=Initializing statics manager... +Initializing message system...=Initializing message system... + [StepsType] dance-couple=couple dance-double=double diff --git a/src/SongManager.cpp b/src/SongManager.cpp index 8fda712dff..997f8f95ba 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -1,6 +1,7 @@ #include "global.h" #include "SongManager.h" #include "arch/LoadingWindow/LoadingWindow.h" +#include "arch/ArchHooks/ArchHooks.h" #include "AnnouncerManager.h" #include "BackgroundUtil.h" #include "BannerCache.h" @@ -253,7 +254,7 @@ void SongManager::LoadStepManiaSongDir( RString sDir ) songCount = 0; FOREACH_CONST( RString, arrayGroupDirs, s ) // foreach dir in /Songs/ { - + if(HOOKS->UserQuit()) break; RString sGroupDirName = *s; SanityCheckGroupDir(sDir+sGroupDirName); @@ -291,6 +292,7 @@ void SongManager::LoadStepManiaSongDir( RString sDir ) for( unsigned j=0; j< arraySongDirs.size(); ++j ) // for each song dir { + if(HOOKS->UserQuit()) break; RString sSongDirName = arraySongDirs[j]; // this is a song directory. Load a new song. @@ -770,6 +772,7 @@ void SongManager::InitCoursesFromDisk() vector vsCourseGroupNames; FOREACH_CONST( RString, vsCourseDirs, sDir ) { + if(HOOKS->UserQuit()) break; // Find all group directories in Courses dir GetDirListing( *sDir + "*", vsCourseGroupNames, true, true ); StripCvsAndSvn( vsCourseGroupNames ); @@ -782,6 +785,7 @@ void SongManager::InitCoursesFromDisk() FOREACH_CONST( RString, vsCourseGroupNames, sCourseGroup ) // for each dir in /Courses/ { + if(HOOKS->UserQuit()) break; // Find all CRS files in this group directory vector vsCoursePaths; GetDirListing( *sCourseGroup + "/*.crs", vsCoursePaths, false, true ); @@ -820,6 +824,7 @@ void SongManager::InitAutogenCourses() Course* pCourse; for( unsigned g=0; gUserQuit()) break; RString sGroupName = saGroupNames[g]; // Generate random courses from each group. @@ -858,6 +863,7 @@ void SongManager::InitAutogenCourses() vector aSongs; unsigned i = 0; do { + if(HOOKS->UserQuit()) break; RString sArtist = i >= apSongs.size()? RString(""): apSongs[i]->GetDisplayArtist(); RString sTranslitArtist = i >= apSongs.size()? RString(""): apSongs[i]->GetTranslitArtist(); if( i < apSongs.size() && !sCurArtist.CompareNoCase(sArtist) ) diff --git a/src/StepMania.cpp b/src/StepMania.cpp index b5622e36b4..5b4c687d4c 100644 --- a/src/StepMania.cpp +++ b/src/StepMania.cpp @@ -932,7 +932,20 @@ static void ApplyLogPreferences() Checkpoints::LogCheckpoints( PREFSMAN->m_bLogCheckpoints ); } -static LocalizedString COULDNT_OPEN_LOADING_WINDOW( "StepMania", "Couldn't open any loading windows." ); +static LocalizedString COULDNT_OPEN_LOADING_WINDOW( "LoadingWindow", "Couldn't open any loading windows." ); +static LocalizedString STARTING_SOUND ( "LoadingWindow", "Starting sound subsystem..."); +static LocalizedString INIT_BOOKKEEPER ( "LoadingWindow", "Initializing bookkeeper..."); +static LocalizedString START_LIGHTS ( "LoadingWindow", "Starting lights subsystem..."); +static LocalizedString LOAD_GAMETYPE ( "LoadingWindow", "Loading game type..."); +static LocalizedString BUILD_SONG_CACHE_INDEX ( "LoadingWindow", "Building song cache index..."); +static LocalizedString LOAD_BANNER_CACHE ( "LoadingWindow", "Loading banner cache..."); +static LocalizedString INIT_MEMCARD ( "LoadingWindow", "Initializing memory card system..."); +static LocalizedString INIT_CHARS ( "LoadingWindow", "Initializing character system..."); +static LocalizedString INIT_PROFILES ( "LoadingWindow", "Initializing profile system..."); +static LocalizedString UPDATE_POPULAR ( "LoadingWindow", "Updating popular song list..."); +static LocalizedString UPDATE_COURSE_RANKS ( "LoadingWindow", "Updating course rankings..."); +static LocalizedString INIT_STATICS ( "LoadingWindow", "Initializing statics manager..."); +static LocalizedString INIT_MESSAGE ( "LoadingWindow", "Initializing message system..."); int main(int argc, char* argv[]) { @@ -1060,65 +1073,76 @@ int main(int argc, char* argv[]) if( PREFSMAN->m_iSoundWriteAhead ) LOG->Info( "Sound writeahead has been overridden to %i", PREFSMAN->m_iSoundWriteAhead.Get() ); - pLoadingWindow->SetText("Starting sound subsystem..."); + pLoadingWindow->SetText(STARTING_SOUND); SOUNDMAN = new RageSoundManager; SOUNDMAN->Init(); SOUNDMAN->SetMixVolume(); SOUND = new GameSoundManager; - pLoadingWindow->SetText("Initializing bookkeeper..."); + pLoadingWindow->SetText(INIT_BOOKKEEPER); BOOKKEEPER = new Bookkeeper; - pLoadingWindow->SetText("Starting lights subsystem..."); + pLoadingWindow->SetText(START_LIGHTS); LIGHTSMAN = new LightsManager; INPUTFILTER = new InputFilter; INPUTMAPPER = new InputMapper; - pLoadingWindow->SetText("Loading game type..."); + pLoadingWindow->SetText(LOAD_GAMETYPE); StepMania::ChangeCurrentGame( GAMESTATE->GetCurrentGame() ); INPUTQUEUE = new InputQueue; - pLoadingWindow->SetText("Building song cache index..."); + pLoadingWindow->SetText(BUILD_SONG_CACHE_INDEX); SONGINDEX = new SongCacheIndex; - pLoadingWindow->SetText("Loading banner cache..."); + pLoadingWindow->SetText(LOAD_BANNER_CACHE); BANNERCACHE = new BannerCache; //BACKGROUNDCACHE = new BackgroundCache; +#define earlyBail if( ArchHooks::UserQuit() ) { \ + ShutdownGame(); \ + SAFE_DELETE( pLoadingWindow ); \ + return 0; \ + } \ + // depends on SONGINDEX: SONGMAN = new SongManager; SONGMAN->InitAll(); // this takes a long time + earlyBail CRYPTMAN = new CryptManager; // need to do this before ProfileMan if( PREFSMAN->m_bSignProfileData ) CRYPTMAN->GenerateGlobalKeys(); - pLoadingWindow->SetText("Initializing memory card system..."); + earlyBail + pLoadingWindow->SetText(INIT_MEMCARD); MEMCARDMAN = new MemoryCardManager; - pLoadingWindow->SetText("Initializing character system..."); + earlyBail + pLoadingWindow->SetText(INIT_CHARS); + earlyBail CHARMAN = new CharacterManager; - pLoadingWindow->SetText("Initializing profile system..."); + pLoadingWindow->SetText(INIT_PROFILES); + earlyBail PROFILEMAN = new ProfileManager; PROFILEMAN->Init(); // must load after SONGMAN + earlyBail UNLOCKMAN = new UnlockManager; - pLoadingWindow->SetText("Updating popular song list..."); + pLoadingWindow->SetText(UPDATE_POPULAR); + earlyBail SONGMAN->UpdatePopular(); SONGMAN->UpdatePreferredSort(); + earlyBail NSMAN = new NetworkSyncManager( pLoadingWindow ); - pLoadingWindow->SetText("Initializing message system..."); + pLoadingWindow->SetText(INIT_MESSAGE); MESSAGEMAN = new MessageManager; - pLoadingWindow->SetText("Initializing statics manager..."); + pLoadingWindow->SetText(INIT_STATICS); STATSMAN = new StatsManager; + earlyBail // Initialize which courses are ranking courses here. - pLoadingWindow->SetText("Updating course rankings..."); + pLoadingWindow->SetText(UPDATE_COURSE_RANKS); SONGMAN->UpdateRankingCourses(); + earlyBail - SAFE_DELETE( pLoadingWindow ); // destroy this before init'ing Display - - /* If the user has tried to quit during the loading, do it before creating - * the main window. This prevents going to full screen just to quit. */ - if( ArchHooks::UserQuit() ) - { - ShutdownGame(); - return 0; - } + // destroy this before init'ing Display, for now + // we will lose the rights to be focused, but that's not too important + // when we are going fullscreen + SAFE_DELETE( pLoadingWindow ); StartDisplay(); diff --git a/src/arch/LoadingWindow/LoadingWindow_Win32.cpp b/src/arch/LoadingWindow/LoadingWindow_Win32.cpp index 8412965205..96b043c3d4 100644 --- a/src/arch/LoadingWindow/LoadingWindow_Win32.cpp +++ b/src/arch/LoadingWindow/LoadingWindow_Win32.cpp @@ -1,289 +1,351 @@ -#include "global.h" -#include "RageUtil.h" - -#include "LoadingWindow_Win32.h" -#include "RageFileManager.h" -#include "archutils/win32/WindowsResources.h" -#include "archutils/win32/WindowIcon.h" -#include "archutils/win32/ErrorStrings.h" -#include -#include "CommCtrl.h" -#include "RageSurface_Load.h" -#include "RageSurface.h" -#include "RageSurfaceUtils.h" -#include "RageLog.h" -#include "ProductInfo.h" -#include "LocalizedString.h" - -#include "RageSurfaceUtils_Zoom.h" -static HBITMAP g_hBitmap = NULL; - -#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") - -// Load a RageSurface into a GDI surface. -static HBITMAP LoadWin32Surface( RageSurface *&s ) -{ - RageSurfaceUtils::ConvertSurface( s, s->w, s->h, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0 ); - - HDC hScreen = GetDC(NULL); - ASSERT_M( hScreen, werr_ssprintf(GetLastError(), "hScreen") ); - - HBITMAP bitmap = CreateCompatibleBitmap( hScreen, s->w, s->h ); - ASSERT_M( bitmap, werr_ssprintf(GetLastError(), "CreateCompatibleBitmap") ); - - HDC BitmapDC = CreateCompatibleDC( hScreen ); - SelectObject( BitmapDC, bitmap ); - - // This is silly, but simple. We only do this once, on a small image. - for( int y = 0; y < s->h; ++y ) - { - unsigned const char *line = ((unsigned char *) s->pixels) + (y * s->pitch); - for( int x = 0; x < s->w; ++x ) - { - unsigned const char *data = line + (x*s->format->BytesPerPixel); - - SetPixelV( BitmapDC, x, y, RGB( data[3], data[2], data[1] ) ); - } - } - - SelectObject( BitmapDC, NULL ); - DeleteObject( BitmapDC ); - - ReleaseDC( NULL, hScreen ); - - return bitmap; -} - -static HBITMAP LoadWin32Surface( RString sFile, HWND hWnd ) -{ - RString error; - RageSurface *pSurface = RageSurfaceUtils::LoadFile( sFile, error ); - if( pSurface == NULL ) - return NULL; - - /* Resize the splash image to fit the dialog. Stretch to fit horizontally, - * maintaining aspect ratio. */ - { - RECT r; - GetClientRect( hWnd, &r ); - - int iWidth = r.right; - float fRatio = (float) iWidth / pSurface->w; - int iHeight = lrintf( pSurface->h * fRatio ); - - RageSurfaceUtils::Zoom( pSurface, iWidth, iHeight ); - } - - HBITMAP ret = LoadWin32Surface( pSurface ); - delete pSurface; - return ret; -} - -INT_PTR CALLBACK LoadingWindow_Win32::DlgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) -{ - LoadingWindow_Win32 *self; - - if(msg==WM_INITDIALOG) { - self=(LoadingWindow_Win32 *)lParam; - SetWindowLong(hWnd,DWL_USER,(LONG)self); - } else { - self=(LoadingWindow_Win32 *)GetWindowLong(hWnd,DWL_USER); - } - - switch( msg ) - { - case WM_INITDIALOG: - { - vector vs; - GetDirListing( "Data/splash*.png", vs, false, true ); - if( !vs.empty() ) - g_hBitmap = LoadWin32Surface( vs[0], hWnd ); - } - if( g_hBitmap == NULL ) - g_hBitmap = LoadWin32Surface( "Data/splash.bmp", hWnd ); - SendMessage( - GetDlgItem(hWnd,IDC_SPLASH), - STM_SETIMAGE, - (WPARAM) IMAGE_BITMAP, - (LPARAM) (HANDLE) g_hBitmap ); - SetWindowTextA( hWnd, PRODUCT_ID ); - - break; - - case WM_CLOSE: - return FALSE; - - case WM_DESTROY: - DeleteObject( g_hBitmap ); - g_hBitmap = NULL; - self->runMessageLoop=false; - self->hwnd=NULL; - return TRUE; - break; - - case WM_APP: - DestroyWindow(hWnd); - self->runMessageLoop=false; - ExitThread(0); - return TRUE; - break; - } - - return FALSE; -} - -void LoadingWindow_Win32::SetIcon( const RageSurface *pIcon ) -{ - if( g_hBitmap != NULL ) - DestroyIcon( m_hIcon ); - - m_hIcon = IconFromSurface( pIcon ); - if( m_hIcon != NULL ) - SetClassLong( hwnd, GCL_HICON, (LONG) m_hIcon ); -} - -void LoadingWindow_Win32::SetSplash( const RString sPath ) -{ - if( g_hBitmap != NULL ) - { - DeleteObject( g_hBitmap ); - g_hBitmap = NULL; - } - - g_hBitmap = LoadWin32Surface( sPath, hwnd ); - if( g_hBitmap != NULL ) - { - SendDlgItemMessage( - hwnd, IDC_SPLASH, - STM_SETIMAGE, - (WPARAM) IMAGE_BITMAP, - (LPARAM) (HANDLE) g_hBitmap - ); - } -} - -LoadingWindow_Win32::LoadingWindow_Win32() -{ - INITCOMMONCONTROLSEX cceData; - cceData.dwSize=sizeof(INITCOMMONCONTROLSEX); - cceData.dwICC=ICC_PROGRESS_CLASS; - InitCommonControlsEx(&cceData); - - m_hIcon = NULL; - - runMessageLoop=true; - - guiReadyEvent=CreateEvent(NULL,FALSE,FALSE,NULL); - - pumpThread=CreateThread(NULL, NULL, MessagePump, (void *)this, 0, &pumpThreadId); - - WaitForSingleObject(guiReadyEvent,INFINITE); - - for( unsigned i = 0; i < 3; ++i ) - text[i] = "ABC"; /* always set on first call */ - SetText( "" ); -} - -LoadingWindow_Win32::~LoadingWindow_Win32() -{ - SendMessage(hwnd,WM_APP,0,0); - //SendMessage(hwnd,WM_NULL,0,0); - WaitForSingleObject(pumpThread,INFINITE); - if(guiReadyEvent) - CloseHandle(guiReadyEvent); - if( m_hIcon != NULL ) - DestroyIcon( m_hIcon ); -} - -DWORD WINAPI LoadingWindow_Win32::MessagePump(LPVOID thisAsVoidPtr) -{ - LoadingWindow_Win32 *self=(LoadingWindow_Win32 *)thisAsVoidPtr; - - self->hwnd = CreateDialogParam( self->handle.Get(), MAKEINTRESOURCE(IDD_LOADING_DIALOG), NULL, DlgProc, (LPARAM)thisAsVoidPtr); - - SetEvent(self->guiReadyEvent); - - // Run the message loop in a separate thread to keep the gui responsive during the loading - MSG msg; - while(self->runMessageLoop && GetMessage(&msg, self->hwnd, 0, 0 ) ) - { - if(IsDialogMessage(self->hwnd,&msg)) continue; - DispatchMessage( &msg ); - } - - return msg.wParam; -} - -void LoadingWindow_Win32::SetText( RString sText ) -{ - vector asMessageLines; - split( sText, "\n", asMessageLines, false ); - while( asMessageLines.size() < 3 ) - asMessageLines.push_back( "" ); - - const int msgid[] = { IDC_STATIC_MESSAGE1, IDC_STATIC_MESSAGE2, IDC_STATIC_MESSAGE3 }; - for( unsigned i = 0; i < 3; ++i ) - { - if( text[i] == asMessageLines[i] ) - continue; - text[i] = asMessageLines[i]; - - HWND hwndItem = ::GetDlgItem( hwnd, msgid[i] ); - - ::SetWindowText( hwndItem, ConvertUTF8ToACP(asMessageLines[i]).c_str() ); - } -} - -void LoadingWindow_Win32::SetProgress(const int progress) -{ - m_progress=progress; - HWND hwndItem = ::GetDlgItem( hwnd, IDC_PROGRESS ); - ::SendMessage(hwndItem,PBM_SETPOS,progress,0); -} - -void LoadingWindow_Win32::SetTotalWork(const int totalWork) -{ - m_totalWork=totalWork; - HWND hwndItem = ::GetDlgItem( hwnd, IDC_PROGRESS ); - SendMessage(hwndItem,PBM_SETRANGE32,0,totalWork); -} - -void LoadingWindow_Win32::SetIndeterminate(bool indeterminate) { - m_indeterminate=indeterminate; - - HWND hwndItem = ::GetDlgItem( hwnd, IDC_PROGRESS ); - - if(indeterminate) { - SetWindowLong(hwndItem,GWL_STYLE, PBS_MARQUEE | GetWindowLong(hwndItem,GWL_STYLE)); - SendMessage(hwndItem,PBM_SETMARQUEE,1,0); - } else { - SendMessage(hwndItem,PBM_SETMARQUEE,0,0); - SetWindowLong(hwndItem,GWL_STYLE, (~PBS_MARQUEE) & GetWindowLong(hwndItem,GWL_STYLE)); - } - -} - -/* - * (c) 2001-2004 Chris Danford, Glenn Maynard - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ +#include "global.h" +#include "RageUtil.h" + +#include "LoadingWindow_Win32.h" +#include "RageFileManager.h" +#include "archutils/win32/WindowsResources.h" +#include "archutils/win32/WindowIcon.h" +#include "archutils/win32/ErrorStrings.h" +#include "arch/ArchHooks/ArchHooks.h" +#include +#include "CommCtrl.h" +#include "RageSurface_Load.h" +#include "RageSurface.h" +#include "RageSurfaceUtils.h" +#include "RageLog.h" +#include "ProductInfo.h" +#include "LocalizedString.h" + + +#include "RageSurfaceUtils_Zoom.h" +static HBITMAP g_hBitmap = NULL; + +#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") + +// Load a RageSurface into a GDI surface. +static HBITMAP LoadWin32Surface( RageSurface *&s ) +{ + RageSurfaceUtils::ConvertSurface( s, s->w, s->h, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0 ); + + HDC hScreen = GetDC(NULL); + ASSERT_M( hScreen, werr_ssprintf(GetLastError(), "hScreen") ); + + HBITMAP bitmap = CreateCompatibleBitmap( hScreen, s->w, s->h ); + ASSERT_M( bitmap, werr_ssprintf(GetLastError(), "CreateCompatibleBitmap") ); + + HDC BitmapDC = CreateCompatibleDC( hScreen ); + SelectObject( BitmapDC, bitmap ); + + // This is silly, but simple. We only do this once, on a small image. + for( int y = 0; y < s->h; ++y ) + { + unsigned const char *line = ((unsigned char *) s->pixels) + (y * s->pitch); + for( int x = 0; x < s->w; ++x ) + { + unsigned const char *data = line + (x*s->format->BytesPerPixel); + + SetPixelV( BitmapDC, x, y, RGB( data[3], data[2], data[1] ) ); + } + } + + SelectObject( BitmapDC, NULL ); + DeleteObject( BitmapDC ); + + ReleaseDC( NULL, hScreen ); + + return bitmap; +} + +static HBITMAP LoadWin32Surface( RString sFile, HWND hWnd ) +{ + RString error; + RageSurface *pSurface = RageSurfaceUtils::LoadFile( sFile, error ); + if( pSurface == NULL ) + return NULL; + + /* Resize the splash image to fit the dialog. Stretch to fit horizontally, + * maintaining aspect ratio. */ + { + RECT r; + GetClientRect( hWnd, &r ); + + int iWidth = r.right; + float fRatio = (float) iWidth / pSurface->w; + int iHeight = lrintf( pSurface->h * fRatio ); + + RageSurfaceUtils::Zoom( pSurface, iWidth, iHeight ); + } + + HBITMAP ret = LoadWin32Surface( pSurface ); + delete pSurface; + return ret; +} + +INT_PTR CALLBACK LoadingWindow_Win32::DlgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) +{ + LoadingWindow_Win32 *self; + + if(msg==WM_INITDIALOG) { + self=(LoadingWindow_Win32 *)lParam; + SetWindowLong(hWnd,DWL_USER,(LONG)self); + } else { + self=(LoadingWindow_Win32 *)GetWindowLong(hWnd,DWL_USER); + } + +#if(WINVER >= 0x0601) + if (self && msg == self->taskbarCreatedEvent && !self->pTaskbarList) { + HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&self->pTaskbarList)); + if (SUCCEEDED(hr)) { + self->pTaskbarList->HrInit(); + if (FAILED(hr)) { + self->pTaskbarList->Release(); + self->pTaskbarList = NULL; + } else { + + + if(self->m_indeterminate) { + self->pTaskbarList->SetProgressState(hWnd, TBPF_INDETERMINATE); + } else { + self->pTaskbarList->SetProgressState(hWnd, TBPF_NORMAL); + self->pTaskbarList->SetProgressValue(hWnd, self->m_progress, self->m_totalWork); + } + } + } + + + } +#endif + + switch( msg ) + { + case WM_INITDIALOG: + { + vector vs; + GetDirListing( "Data/splash*.png", vs, false, true ); + if( !vs.empty() ) + g_hBitmap = LoadWin32Surface( vs[0], hWnd ); + } + if( g_hBitmap == NULL ) + g_hBitmap = LoadWin32Surface( "Data/splash.bmp", hWnd ); + SendMessage( + GetDlgItem(hWnd,IDC_SPLASH), + STM_SETIMAGE, + (WPARAM) IMAGE_BITMAP, + (LPARAM) (HANDLE) g_hBitmap ); + SetWindowTextA( hWnd, PRODUCT_ID ); + + break; + + case WM_CLOSE: + HOOKS->SetUserQuit(); + return FALSE; + + case WM_DESTROY: + +#if(WINVER >= 0x0601) + if (self->pTaskbarList) { + self->pTaskbarList->Release(); + self->pTaskbarList = NULL; + } +#endif + + DeleteObject( g_hBitmap ); + g_hBitmap = NULL; + self->runMessageLoop=false; + self->hwnd=NULL; + return TRUE; + break; + + case WM_APP: + DestroyWindow(hWnd); + self->runMessageLoop=false; + ExitThread(0); + return TRUE; + break; + } + + return FALSE; +} + +void LoadingWindow_Win32::SetIcon( const RageSurface *pIcon ) +{ + if( g_hBitmap != NULL ) + DestroyIcon( m_hIcon ); + + m_hIcon = IconFromSurface( pIcon ); + if( m_hIcon != NULL ) + SetClassLong( hwnd, GCL_HICON, (LONG) m_hIcon ); +} + +void LoadingWindow_Win32::SetSplash( const RString sPath ) +{ + if( g_hBitmap != NULL ) + { + DeleteObject( g_hBitmap ); + g_hBitmap = NULL; + } + + g_hBitmap = LoadWin32Surface( sPath, hwnd ); + if( g_hBitmap != NULL ) + { + SendDlgItemMessage( + hwnd, IDC_SPLASH, + STM_SETIMAGE, + (WPARAM) IMAGE_BITMAP, + (LPARAM) (HANDLE) g_hBitmap + ); + } +} + +LoadingWindow_Win32::LoadingWindow_Win32() +{ + + INITCOMMONCONTROLSEX cceData; + cceData.dwSize=sizeof(INITCOMMONCONTROLSEX); + cceData.dwICC=ICC_PROGRESS_CLASS; + InitCommonControlsEx(&cceData); + +#if(WINVER >= 0x0601) + pTaskbarList=NULL; + + taskbarCreatedEvent=RegisterWindowMessage("TaskbarButtonCreated"); +#endif + + m_hIcon = NULL; + + runMessageLoop=true; + + guiReadyEvent=CreateEvent(NULL,FALSE,FALSE,NULL); + + pumpThread=CreateThread(NULL, NULL, MessagePump, (void *)this, 0, &pumpThreadId); + + WaitForSingleObject(guiReadyEvent,INFINITE); + + for( unsigned i = 0; i < 3; ++i ) + text[i] = "ABC"; /* always set on first call */ + SetText( "" ); +} + +LoadingWindow_Win32::~LoadingWindow_Win32() +{ + SendMessage(hwnd,WM_APP,0,0); + //SendMessage(hwnd,WM_NULL,0,0); + WaitForSingleObject(pumpThread,INFINITE); + if(guiReadyEvent) + CloseHandle(guiReadyEvent); + if( m_hIcon != NULL ) + DestroyIcon( m_hIcon ); +} + +DWORD WINAPI LoadingWindow_Win32::MessagePump(LPVOID thisAsVoidPtr) +{ + LoadingWindow_Win32 *self=(LoadingWindow_Win32 *)thisAsVoidPtr; + + self->hwnd = CreateDialogParam( self->handle.Get(), MAKEINTRESOURCE(IDD_LOADING_DIALOG), NULL, DlgProc, (LPARAM)thisAsVoidPtr); + + SetEvent(self->guiReadyEvent); + + // Run the message loop in a separate thread to keep the gui responsive during the loading + MSG msg; + while(self->runMessageLoop && GetMessage(&msg, self->hwnd, 0, 0 ) ) + { + if(IsDialogMessage(self->hwnd,&msg)) continue; + DispatchMessage( &msg ); + } + + return msg.wParam; +} + +void LoadingWindow_Win32::SetText( RString sText ) +{ + vector asMessageLines; + split( sText, "\n", asMessageLines, false ); + while( asMessageLines.size() < 3 ) + asMessageLines.push_back( "" ); + + const int msgid[] = { IDC_STATIC_MESSAGE1, IDC_STATIC_MESSAGE2, IDC_STATIC_MESSAGE3 }; + for( unsigned i = 0; i < 3; ++i ) + { + if( text[i] == asMessageLines[i] ) + continue; + text[i] = asMessageLines[i]; + + HWND hwndItem = ::GetDlgItem( hwnd, msgid[i] ); + + ::SetWindowText( hwndItem, ConvertUTF8ToACP(asMessageLines[i]).c_str() ); + } +} + +void LoadingWindow_Win32::SetProgress(const int progress) +{ + m_progress=progress; + HWND hwndItem = ::GetDlgItem( hwnd, IDC_PROGRESS ); + ::SendMessage(hwndItem,PBM_SETPOS,progress,0); +#if(WINVER >= 0x0601) + if(pTaskbarList) { + pTaskbarList->SetProgressValue(hwnd, m_progress, m_totalWork); + } +#endif +} + +void LoadingWindow_Win32::SetTotalWork(const int totalWork) +{ + m_totalWork=totalWork; + HWND hwndItem = ::GetDlgItem( hwnd, IDC_PROGRESS ); + SendMessage(hwndItem,PBM_SETRANGE32,0,totalWork); +#if(WINVER >= 0x0601) + if(pTaskbarList) { + pTaskbarList->SetProgressValue(hwnd, m_progress, m_totalWork); + } +#endif +} + +void LoadingWindow_Win32::SetIndeterminate(bool indeterminate) { + m_indeterminate=indeterminate; + + HWND hwndItem = ::GetDlgItem( hwnd, IDC_PROGRESS ); + + if(indeterminate) { +#if(WINVER >= 0x0601) + if(pTaskbarList) { + pTaskbarList->SetProgressState(hwnd, TBPF_INDETERMINATE); + } +#endif + SetWindowLong(hwndItem,GWL_STYLE, PBS_MARQUEE | GetWindowLong(hwndItem,GWL_STYLE)); + SendMessage(hwndItem,PBM_SETMARQUEE,1,0); + } else { + SendMessage(hwndItem,PBM_SETMARQUEE,0,0); + SetWindowLong(hwndItem,GWL_STYLE, (~PBS_MARQUEE) & GetWindowLong(hwndItem,GWL_STYLE)); +#if(WINVER >= 0x0601) + if(pTaskbarList) { + pTaskbarList->SetProgressState(hwnd, TBPF_NORMAL); + } +#endif + } + +} + +/* + * (c) 2001-2004 Chris Danford, Glenn Maynard + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ diff --git a/src/arch/LoadingWindow/LoadingWindow_Win32.h b/src/arch/LoadingWindow/LoadingWindow_Win32.h index 3780c85178..491137aa99 100644 --- a/src/arch/LoadingWindow/LoadingWindow_Win32.h +++ b/src/arch/LoadingWindow/LoadingWindow_Win32.h @@ -3,10 +3,16 @@ #ifndef LOADING_WINDOW_WIN32_H #define LOADING_WINDOW_WIN32_H +#include "global.h" + #include "LoadingWindow.h" #include #include "archutils/Win32/AppInstance.h" +#if(WINVER >= 0x0601) +#include "Shobjidl.h" +#endif + class LoadingWindow_Win32: public LoadingWindow { public: @@ -29,6 +35,11 @@ private: DWORD pumpThreadId; HANDLE guiReadyEvent; +#if(WINVER >= 0x0601) + UINT taskbarCreatedEvent; + ITaskbarList3 *pTaskbarList; +#endif + volatile bool runMessageLoop; static DWORD WINAPI MessagePump(LPVOID thisAsVoidPtr); diff --git a/src/archutils/Win32/arch_setup.h b/src/archutils/Win32/arch_setup.h index c403f26b4c..0b81211d7e 100644 --- a/src/archutils/Win32/arch_setup.h +++ b/src/archutils/Win32/arch_setup.h @@ -66,7 +66,7 @@ C4355: 'this' : used in base member initializer list /* Pull in NT-only definitions. Note that we support Win98 and WinME; you can * make NT calls, but be sure to fall back on 9x if they're not supported. */ -#define _WIN32_WINNT 0x0501 +#define _WIN32_WINNT 0x0601 #define _WIN32_IE 0x0400 // If this isn't defined to 0, VC fails to define things like stat and alloca.