From b769a7a360397acb22c20a05da6c681fb3c62753 Mon Sep 17 00:00:00 2001 From: spx Date: Mon, 29 Mar 2010 21:50:05 +0000 Subject: [PATCH] - Modified the way to handle the "On Desktop". This affects all of Windows versions. - Added "LoadOrder" to handle the skins' loading order. - Changed the way to update and save the network statistics. --- Library/MeterWindow.cpp | 220 ++++++----------------- Library/MeterWindow.h | 5 +- Library/Rainmeter.cpp | 273 ++++++++++++++-------------- Library/Rainmeter.h | 15 +- Library/System.cpp | 382 +++++++++++++++++++++++++++++----------- Library/System.h | 15 +- Library/TrayWindow.cpp | 16 +- Library/TrayWindow.h | 2 + 8 files changed, 527 insertions(+), 401 deletions(-) diff --git a/Library/MeterWindow.cpp b/Library/MeterWindow.cpp index ee3473d9..7face4a6 100644 --- a/Library/MeterWindow.cpp +++ b/Library/MeterWindow.cpp @@ -93,6 +93,7 @@ CMeterWindow::CMeterWindow(std::wstring& path, std::wstring& config, std::wstrin m_WindowUpdate = 1000; m_TransitionUpdate = 100; m_ActiveTransition = false; + m_HasNetMeasures = false; m_WindowHide = HIDEMODE_NONE; m_WindowStartHidden = false; m_SnapEdges = true; @@ -294,7 +295,7 @@ void CMeterWindow::IgnoreAeroPeek() ** This deletes everything and rebuilds the config again. ** */ -void CMeterWindow::Refresh(bool init) +void CMeterWindow::Refresh(bool init, bool all) { assert(m_Rainmeter != NULL); @@ -316,13 +317,6 @@ void CMeterWindow::Refresh(bool init) KillTimer(m_Window, MOUSETIMER); // Kill the timer KillTimer(m_Window, FADETIMER); // Kill the timer - if (!m_ChildWindow && GetAncestor(m_Window, GA_PARENT) != GetDesktopWindow()) - { - // Reset to the top-level window - m_PreventMoving = true; // Prevent moving the window by SetParent - SetParent(m_Window, NULL); - } - std::list::iterator i = m_Measures.begin(); for( ; i != m_Measures.end(); i++) { @@ -348,6 +342,8 @@ void CMeterWindow::Refresh(bool init) m_FontCollection = NULL; } + ZPOSITION oldZPos = m_WindowZPosition; + //TODO: Should these be moved to a Reload command instead of hitting the disk on every refresh ReadConfig(); // Read the general settings ReadSkin(); @@ -373,10 +369,7 @@ void CMeterWindow::Refresh(bool init) MapCoordsToScreen(m_ScreenX, m_ScreenY, m_WindowW, m_WindowH); } - ZPOSITION zPos = m_WindowZPosition; - m_WindowZPosition = ZPOSITION_NORMAL; // Handles as the normal window temporarily - SetWindowPos(m_Window, NULL, m_ScreenX, m_ScreenY, m_WindowW, m_WindowH, SWP_NOZORDER | SWP_NOACTIVATE); - m_WindowZPosition = zPos; + SetWindowPos(m_Window, NULL, m_ScreenX, m_ScreenY, m_WindowW, m_WindowH, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING); ScreenToWindow(); @@ -393,7 +386,10 @@ void CMeterWindow::Refresh(bool init) UpdateTransparency(m_AlphaValue, true); - ChangeZPos(m_WindowZPosition); + if (init || all || oldZPos != m_WindowZPosition) + { + ChangeZPos(m_WindowZPosition, init || all); + } m_Rainmeter->SetCurrentParser(NULL); @@ -474,17 +470,6 @@ void CMeterWindow::MapCoordsToScreen(int& x, int& y, int w, int h) */ void CMeterWindow::MoveWindow(int x, int y) { - // Convert the screen coordinates to the client coordinates of the shell window - if (!m_ChildWindow && m_WindowZPosition == ZPOSITION_ONDESKTOP && GetAncestor(m_Window, GA_PARENT) != GetDesktopWindow()) - { - POINT pos = {x, y}; - if (ScreenToClient(GetAncestor(m_Window, GA_PARENT), &pos)) - { - x = pos.x; - y = pos.y; - } - } - SetWindowPos(m_Window, NULL, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); ScreenToWindow(); @@ -501,7 +486,7 @@ void CMeterWindow::MoveWindow(int x, int y) ** Sets the window's z-position ** */ -void CMeterWindow::ChangeZPos(ZPOSITION zPos) +void CMeterWindow::ChangeZPos(ZPOSITION zPos, bool all) { if(!m_ChildWindow) { @@ -517,104 +502,60 @@ void CMeterWindow::ChangeZPos(ZPOSITION zPos) break; case ZPOSITION_ONBOTTOM: - winPos = HWND_BOTTOM; - break; - - case ZPOSITION_ONDESKTOP: - if (!m_NativeTransparency || !CSystem::GetDwmCompositionEnabled()) + if (all) { - winPos = HWND_BOTTOM; - - // Set the window's parent to progman, so it stays always on desktop - HWND ProgmanHwnd = CSystem::GetShellDesktopWindow(); - - if (ProgmanHwnd && (parent != ProgmanHwnd)) + if (CSystem::GetShowDesktop()) { - m_PreventMoving = true; // Prevent moving the window by SetParent - SetParent(m_Window, ProgmanHwnd); + // Insert after the tray window temporarily to keep order + winPos = Rainmeter->GetTrayWindow()->GetWindow(); + } + else + { + // Insert after the helper window + winPos = CSystem::GetHelperWindow(); } - //else - //{ - // return; // The window is already on desktop - //} } else { - if (parent != GetDesktopWindow()) - { - m_PreventMoving = true; // Prevent moving the window by SetParent - SetParent(m_Window, NULL); + winPos = HWND_BOTTOM; + } + break; - IgnoreAeroPeek(); + case ZPOSITION_ONDESKTOP: + if (CSystem::GetShowDesktop()) + { + // Set WS_EX_TOPMOST flag + SetWindowPos(m_Window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + + if (all) + { + // Insert after the helper window + SetWindowPos(m_Window, CSystem::GetHelperWindow(), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING); } - - if (CSystem::GetShowDesktop()) + else { - bool logging = false; // Set true if you need verbose logging. - std::wstring msg; - - if (logging) - { - msg += (GetWindowLong(m_Window, GWL_EXSTYLE) & WS_EX_TOPMOST) ? L"TOPMOST" : L"NORMAL"; - } - - // Set WS_EX_TOPMOST flag - SetWindowPos(m_Window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING); - - if (logging) - { - msg += L" - "; - msg += (GetWindowLong(m_Window, GWL_EXSTYLE) & WS_EX_TOPMOST) ? L"TOPMOST" : L"NORMAL"; - } - - // Get WorkerW window - HWND WorkerW = CSystem::GetWorkerW(); - // Find the "backmost" topmost window - if (WorkerW) + HWND hwnd = CSystem::GetHelperWindow(); + while (hwnd = ::GetNextWindow(hwnd, GW_HWNDPREV)) { - HWND hwnd = WorkerW; - while (hwnd = ::GetNextWindow(hwnd, GW_HWNDPREV)) + if (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) { - if (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) + // Insert after the found window + if (0 != SetWindowPos(m_Window, hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING)) { - WCHAR className[128], windowText[128]; - - if (logging) - { - GetClassName(hwnd, className, 128); - GetWindowText(hwnd, windowText, 128); - } - - if (0 == SetWindowPos(m_Window, hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING)) - { - if (logging) - { - DebugLog(L" %s: hwnd=0x%08X (WorkerW=0x%08X), hwndInsertAfter=0x%08X (\"%s\" %s) - FAILED", - m_SkinName.c_str(), m_Window, WorkerW, hwnd, windowText, className); - } - continue; - } - - if (logging) - { - msg += L" - "; - msg += (GetWindowLong(m_Window, GWL_EXSTYLE) & WS_EX_TOPMOST) ? L"TOPMOST" : L"NORMAL"; - - DebugLog(L" %s: hwnd=0x%08X (WorkerW=0x%08X), hwndInsertAfter=0x%08X (\"%s\" %s) - %s", - m_SkinName.c_str(), m_Window, WorkerW, hwnd, windowText, className, msg.c_str()); - } - return; + break; } } } - - if (logging) - { - DebugLog(L" %s: hwnd=0x%08X (WorkerW=0x%08X), hwndInsertAfter=HWND_TOPMOST - %s", - m_SkinName.c_str(), m_Window, WorkerW, msg.c_str()); - } - return; + } + return; + } + else + { + if (all) + { + // Insert after the helper window + winPos = CSystem::GetHelperWindow(); } else { @@ -624,18 +565,7 @@ void CMeterWindow::ChangeZPos(ZPOSITION zPos) break; } - if (zPos != ZPOSITION_ONDESKTOP && (parent != GetDesktopWindow())) - { - m_PreventMoving = true; // Prevent moving the window by SetParent - SetParent(m_Window, NULL); - - IgnoreAeroPeek(); - } - - bool refresh = m_Refreshing; - m_Refreshing = true; // Fake refreshing so that the z-position can be changed - SetWindowPos(m_Window, winPos, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - m_Refreshing = refresh; + SetWindowPos(m_Window, winPos, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); } } @@ -1762,6 +1692,8 @@ void CMeterWindow::ReadSkin() // Create the meters and measures + m_HasNetMeasures = false; + // Get all the sections (i.e. different meters, measures and the other stuff) std::vector arraySections = m_Parser.GetSections(); @@ -1791,6 +1723,11 @@ void CMeterWindow::ReadSkin() m_Measures.push_back(measure); m_Parser.AddMeasure(measure); + + if (!m_HasNetMeasures && dynamic_cast((measure))) + { + m_HasNetMeasures = true; + } } } catch (CError& error) @@ -2204,7 +2141,7 @@ void CMeterWindow::Update(bool nodraw) m_UpdateCounter++; // Pre-updates - CMeasureNet::UpdateIFTable(); + if (m_HasNetMeasures) CMeasureNet::UpdateIFTable(); CMeasureCalc::UpdateVariableMap(*this); // Update all measures @@ -2244,10 +2181,6 @@ void CMeterWindow::Update(bool nodraw) } } - // Statistics - CMeasureNet::UpdateStats(); - Rainmeter->WriteStats(false); - if (!nodraw) { if (m_DynamicWindowSize) @@ -3154,17 +3087,6 @@ LRESULT CMeterWindow::OnWindowPosChanging(WPARAM wParam, LPARAM lParam) return DefWindowProc(m_Window, m_Message, wParam, lParam); } - // Convert the client coordinates of the shell window to the screen coordinates - if (!m_ChildWindow && m_WindowZPosition == ZPOSITION_ONDESKTOP && (m_Dragging || !m_NativeTransparency) && GetAncestor(m_Window, GA_PARENT) != GetDesktopWindow()) - { - POINT pos = {wp->x, wp->y}; - if (ClientToScreen(GetAncestor(m_Window, GA_PARENT), &pos)) - { - wp->x = pos.x; - wp->y = pos.y; - } - } - if (m_SnapEdges && !(GetKeyState(VK_CONTROL) & 0x8000 || GetKeyState(VK_SHIFT) & 0x8000)) { // only process movement (ignore anything without winpos values) @@ -3213,17 +3135,6 @@ LRESULT CMeterWindow::OnWindowPosChanging(WPARAM wParam, LPARAM lParam) { MapCoordsToScreen(wp->x, wp->y, m_WindowW, m_WindowH); } - - // Convert the screen coordinates to the client coordinates of the shell window - if (!m_ChildWindow && m_WindowZPosition == ZPOSITION_ONDESKTOP && GetAncestor(m_Window, GA_PARENT) != GetDesktopWindow()) - { - POINT pos = {wp->x, wp->y}; - if (ScreenToClient(GetAncestor(m_Window, GA_PARENT), &pos)) - { - wp->x = pos.x; - wp->y = pos.y; - } - } } return DefWindowProc(m_Window, m_Message, wParam, lParam); @@ -3888,28 +3799,11 @@ LRESULT CMeterWindow::OnMove(WPARAM wParam, LPARAM lParam) m_ScreenX = (SHORT)LOWORD(lParam); m_ScreenY = (SHORT)HIWORD(lParam); - // Convert the client coordinates of the shell window to the screen coordinates - if (!m_ChildWindow && m_WindowZPosition == ZPOSITION_ONDESKTOP && GetAncestor(m_Window, GA_PARENT) != GetDesktopWindow()) - { - POINT pos = {m_ScreenX, m_ScreenY}; - if (ClientToScreen(GetAncestor(m_Window, GA_PARENT), &pos)) - { - m_ScreenX = pos.x; - m_ScreenY = pos.y; - } - } - if (m_Dragging) { ScreenToWindow(); } - // Redraw itself if the window is "On Desktop" - if (!m_ChildWindow && m_WindowZPosition == ZPOSITION_ONDESKTOP && m_NativeTransparency && GetAncestor(m_Window, GA_PARENT) != GetDesktopWindow()) - { - UpdateTransparency(m_TransparencyValue, false); - } - return 0; } diff --git a/Library/MeterWindow.h b/Library/MeterWindow.h index eb5d9f33..014cf4f5 100644 --- a/Library/MeterWindow.h +++ b/Library/MeterWindow.h @@ -134,11 +134,11 @@ public: void DisableMeasure(const WCHAR* name); void EnableMeasure(const WCHAR* name); void ToggleMeasure(const WCHAR* name); - void Refresh(bool init); + void Refresh(bool init, bool all = false); void Redraw(); void MoveWindow(int x, int y); - void ChangeZPos(ZPOSITION zPos); + void ChangeZPos(ZPOSITION zPos, bool all = false); void FadeWindow(int from, int to); Gdiplus::Bitmap* GetDoubleBuffer() { return m_DoubleBuffer; }; @@ -291,6 +291,7 @@ private: int m_WindowUpdate; // Measure update frequency int m_TransitionUpdate; // Transition redraw frequency bool m_ActiveTransition; + bool m_HasNetMeasures; HIDEMODE m_WindowHide; // If true, the window is hidden when mouse is over it bool m_WindowStartHidden; // If true, the window is hidden at startup bool m_SavePosition; // If true, the window's position is saved diff --git a/Library/Rainmeter.cpp b/Library/Rainmeter.cpp index 8ddcf2bb..f8cfef53 100644 --- a/Library/Rainmeter.cpp +++ b/Library/Rainmeter.cpp @@ -245,55 +245,11 @@ void BangWithArgs(BANGCOMMAND bang, const WCHAR* arg, size_t numOfArgs) else { // No config defined -> apply to all. - - // Make the sending order by using order of the config sections - std::vector sections; - { - CConfigParser parser; - parser.Initialize(Rainmeter->GetIniFile().c_str(), Rainmeter); - sections = parser.GetSections(); - } - std::vector windows(sections.size(), NULL); - std::vector windowsMissing; - std::map::iterator iter = Rainmeter->GetAllMeterWindows().begin(); for (; iter != Rainmeter->GetAllMeterWindows().end(); iter++) { - CMeterWindow* window = (*iter).second; - bool find = false; - - for (size_t i = 0; i < windows.size(); i++) - { - if (windows[i] == NULL && wcsicmp(sections[i].c_str(), window->GetSkinName().c_str()) == 0) - { - windows[i] = window; - find = true; - break; - } - } - - if (!find) // Not found for some reasons - { - windowsMissing.push_back(window); - } - } - - // Apply to all - std::vector::const_reverse_iterator iter2 = windows.rbegin(); - for ( ; iter2 != windows.rend(); iter2++) - { - if (*iter2) - { - (*iter2)->RunBang(bang, argument.c_str()); - } - } - for (size_t i = 0; i < windowsMissing.size(); i++) - { - if (windowsMissing[i]) - { - windowsMissing[i]->RunBang(bang, argument.c_str()); - } + ((*iter).second)->RunBang(bang, argument.c_str()); } } } @@ -448,6 +404,21 @@ void RainmeterRefresh(HWND, const char* arg) BangWithArgs(BANG_REFRESH, ConvertToWide(arg).c_str(), 0); } +/* +** RainmeterRefreshApp +** +** Callback for the !RainmeterRefreshApp bang +** +*/ +void RainmeterRefreshApp(HWND, const char* arg) +{ + if (Rainmeter) + { + // Refresh needs to be delayed since it crashes if done during Update() + PostMessage(Rainmeter->GetTrayWindow()->GetWindow(), WM_DELAYED_REFRESH_ALL, (WPARAM)NULL, (LPARAM)NULL); + } +} + /* ** RainmeterRedraw ** @@ -745,14 +716,16 @@ CRainmeter::~CRainmeter() if (m_TrayWindow) delete m_TrayWindow; + CSystem::Finalize(); + + CMeasureNet::UpdateIFTable(); + CMeasureNet::UpdateStats(); WriteStats(true); CMeasureNet::FinalizeNewApi(); CMeterString::FreeFontCache(); - CSystem::Finalize(); - GdiplusShutdown(m_GDIplusToken); } @@ -1012,6 +985,7 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) if (m_TrayWindow && m_TrayWindow->GetWindow()) ::SendMessage(GetLitestepWnd(), LM_REGISTERMESSAGE, (WPARAM)m_TrayWindow->GetWindow(), (LPARAM)Msgs); AddBangCommand("!RainmeterRefresh", RainmeterRefresh); + AddBangCommand("!RainmeterRefreshApp", RainmeterRefreshApp); AddBangCommand("!RainmeterRedraw", RainmeterRedraw); AddBangCommand("!RainmeterHide", RainmeterHide); AddBangCommand("!RainmeterShow", RainmeterShow); @@ -1040,57 +1014,16 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) AddBangCommand("!RainmeterSetVariable", RainmeterSetVariable); } - // Make the starting order by using order of the config sections - std::vector sections; - { - CConfigParser parser; - parser.Initialize(m_IniFile.c_str(), this); - sections = parser.GetSections(); - } - std::vector > startup(sections.size(), std::pair(0, 0)); - std::vector > startupMissing; - - for (size_t i = 0; i < m_ConfigStrings.size(); i++) - { - if (m_ConfigStrings[i].active > 0 && m_ConfigStrings[i].active <= (int)m_ConfigStrings[i].iniFiles.size()) - { - bool find = false; - - for (size_t j = 0; j < startup.size(); j++) - { - if (startup[j].second == 0 && wcsicmp(sections[j].c_str(), m_ConfigStrings[i].config.c_str()) == 0) - { - startup[j].first = i; - startup[j].second = m_ConfigStrings[i].active; - find = true; - break; - } - } - - if (!find) // Not found for some reasons - { - startupMissing.push_back(std::pair(i, m_ConfigStrings[i].active)); - } - } - } - // Create meter windows for active configs - std::vector >::const_reverse_iterator iter = startup.rbegin(); - for ( ; iter != startup.rend(); iter++) + std::multimap::const_iterator iter = m_ConfigOrders.begin(); + for ( ; iter != m_ConfigOrders.end(); iter++) { - if ((*iter).second > 0) - { - ActivateConfig((*iter).first, (*iter).second - 1); - } - } - for (size_t i = 0; i < startupMissing.size(); i++) - { - if (startupMissing[i].second > 0) - { - ActivateConfig(startupMissing[i].first, startupMissing[i].second - 1); - } + ActivateConfig((*iter).second.id, (*iter).second.active - 1); } + //Clear order + m_ConfigOrders.clear(); + return Result; // Alles OK } @@ -1488,6 +1421,72 @@ CMeterWindow* CRainmeter::GetMeterWindow(HWND hwnd) return NULL; } +void CRainmeter::SetConfigOrder(const std::wstring& config, int index, int active) +{ + WCHAR buffer[256]; + int order; + + if (GetPrivateProfileString(config.c_str(), L"LoadOrder", L"", buffer, 256, m_IniFile.c_str()) > 0) + { + if (wcsicmp(buffer, L"LAST") == 0) + { + order = INT_MAX; + } + else if (wcsicmp(buffer, L"FIRST") == 0) + { + order = INT_MIN; + } + else + { + order = _wtoi(buffer); + } + } + else // LoadOrder not exists + { + //WritePrivateProfileString(config.c_str(), L"LoadOrder", L"0", m_IniFile.c_str()); + order = 0; + } + + std::multimap::iterator iter = m_ConfigOrders.begin(); + for ( ; iter != m_ConfigOrders.end(); iter++) + { + if ((*iter).second.config == config) // already exists + { + if ((*iter).first != order || (*iter).second.id != index || (*iter).second.active != active) + { + m_ConfigOrders.erase(iter); + break; + } + else + { + return; + } + } + } + + // Add CONFIGORDER + CONFIGORDER configOrder; + configOrder.config = config; + configOrder.id = index; + configOrder.active = active; + + m_ConfigOrders.insert(std::pair(order, configOrder)); +} + +int CRainmeter::GetLoadOrder(const std::wstring& config) +{ + std::multimap::const_iterator iter = m_ConfigOrders.begin(); + for ( ; iter != m_ConfigOrders.end(); iter++) + { + if ((*iter).second.config == config) + { + return (*iter).first; + } + } + + return 0; +} + /* ** Quit ** @@ -1504,6 +1503,7 @@ void CRainmeter::Quit(HINSTANCE dllInst) if (m_TrayWindow && m_TrayWindow->GetWindow()) ::SendMessage(GetLitestepWnd(), LM_UNREGISTERMESSAGE, (WPARAM)m_TrayWindow->GetWindow(), (LPARAM)Msgs); RemoveBangCommand("!RainmeterRefresh"); + RemoveBangCommand("!RainmeterRefreshApp"); RemoveBangCommand("!RainmeterRedraw"); RemoveBangCommand("!RainmeterHide"); RemoveBangCommand("!RainmeterShow"); @@ -1542,6 +1542,7 @@ void CRainmeter::ScanForConfigs(std::wstring& path) { m_ConfigStrings.clear(); m_ConfigMenu.clear(); + m_ConfigOrders.clear(); ScanForConfigsRecursive(path, L"", 0, m_ConfigMenu, false); } @@ -1664,11 +1665,8 @@ BOOL CRainmeter::ExecuteBang(const std::wstring& bang, const std::wstring& arg, } else if (wcsicmp(bang.c_str(), L"!RainmeterRefreshApp") == 0) { - // Read skins and settings - Rainmeter->ReloadSettings(); - // Refresh all - RainmeterRefresh(m_TrayWindow->GetWindow(), NULL); - + // Refresh needs to be delayed since it crashes if done during Update() + PostMessage(m_TrayWindow->GetWindow(), WM_DELAYED_REFRESH_ALL, (WPARAM)NULL, (LPARAM)NULL); } else if (wcsicmp(bang.c_str(), L"!RainmeterRedraw") == 0) { @@ -2035,6 +2033,8 @@ void CRainmeter::ReadGeneralSettings(std::wstring& iniFile) if (active > 0 && active <= (int)m_ConfigStrings[i].iniFiles.size()) { m_ConfigStrings[i].active = active; + + SetConfigOrder(m_ConfigStrings[i].config, i, active); } } } @@ -2067,39 +2067,52 @@ bool CRainmeter::SetActiveConfig(std::wstring& skinName, std::wstring& skinIni) } /* -** Refresh +** RefreshAll +** +** Refreshes all active meter windows. +** Note: This function calls CMeterWindow::Refresh() directly for synchronization. Be careful about crash. ** -** Refreshes Rainmeter. If argument is given the config is refreshed -** otherwise all active meters are refreshed */ -//void CRainmeter::Refresh(const WCHAR* arg) -//{ -// std::wstring config, iniFile; -// -// try -// { -// if (arg != NULL && wcslen(arg) > 0) -// { -// std::wstring config = arg; -// CMeterWindow* meterWindow = GetMeterWindow(config); -// meterWindow->Refresh(false); -// } -// else -// { -// std::map::iterator iter = m_Meters.begin(); -// -// // Refresh all -// for (; iter != m_Meters.end(); iter++) -// { -// (*iter).second->Refresh(false); -// } -// } -// } -// catch(CError& error) -// { -// MessageBox(NULL, error.GetString().c_str(), APPNAME, MB_OK | MB_TOPMOST | MB_ICONEXCLAMATION); -// } -//} +void CRainmeter::RefreshAll() +{ + // Read skins and settings + ReloadSettings(); + + // Make the sending order by using LoadOrder + std::multimap windows; + + std::map::iterator iter = m_Meters.begin(); + for (; iter != m_Meters.end(); iter++) + { + if ((*iter).second) + { + windows.insert(std::pair(GetLoadOrder((*iter).first), (*iter).second)); + } + } + + // Prepare the helper window + CSystem::PrepareHelperWindow(CSystem::GetWorkerW()); + + // Refresh all + std::multimap::const_iterator iter2 = windows.begin(); + for ( ; iter2 != windows.end(); iter2++) + { + if ((*iter2).second) + { + try + { + (*iter2).second->Refresh(false, true); + } + catch (CError& error) + { + MessageBox((*iter2).second->GetWindow(), error.GetString().c_str(), APPNAME, MB_OK | MB_TOPMOST | MB_ICONEXCLAMATION); + } + } + } + + // Clear order + m_ConfigOrders.clear(); +} /* ** ReadStats diff --git a/Library/Rainmeter.h b/Library/Rainmeter.h index 6ed849b8..8ce02898 100644 --- a/Library/Rainmeter.h +++ b/Library/Rainmeter.h @@ -52,6 +52,7 @@ void RainmeterActivateConfig(HWND, const char* arg); void RainmeterDeactivateConfig(HWND, const char* arg); void RainmeterToggleConfig(HWND, const char* arg); void RainmeterRefresh(HWND, const char* arg); +void RainmeterRefreshApp(HWND, const char* arg); void RainmeterRedraw(HWND, const char* arg); void RainmeterToggleMeasure(HWND, const char* arg); void RainmeterEnableMeasure(HWND, const char* arg); @@ -92,6 +93,13 @@ public: int active; }; + struct CONFIGORDER + { + std::wstring config; + int id; + int active; + }; + struct CONFIGMENU { std::wstring name; @@ -115,6 +123,7 @@ public: CMeterWindow* GetMeterWindow(HWND hwnd); std::map& GetAllMeterWindows() { return m_Meters; }; const std::vector& GetAllConfigs() { return m_ConfigStrings; }; + const std::multimap& GetAllConfigOrders() { return m_ConfigOrders; } const std::vector& GetAllThemes() { return m_Themes; }; void ActivateConfig(int configIndex, int iniIndex); @@ -163,6 +172,8 @@ public: std::wstring ParseCommand(const WCHAR* command, CMeterWindow* meterWindow); void ExecuteCommand(const WCHAR* command, CMeterWindow* meterWindow); + void RefreshAll(); + void ClearDeleteLaterList(); static PLATFORM IsNT(); @@ -175,8 +186,9 @@ private: void ScanForConfigs(std::wstring& path); void ScanForThemes(std::wstring& path); void ReadGeneralSettings(std::wstring& path); + void SetConfigOrder(const std::wstring& config, int index, int active); + int GetLoadOrder(const std::wstring& config); bool SetActiveConfig(std::wstring& skinName, std::wstring& skinIni); - //void Refresh(const WCHAR* arg); HMENU CreateSkinMenu(CMeterWindow* meterWindow, int index); void ChangeSkinIndex(HMENU subMenu, int index); int ScanForConfigsRecursive(std::wstring& path, std::wstring base, int index, std::vector& menu, bool DontRecurse); @@ -193,6 +205,7 @@ private: std::vector m_ConfigStrings; // All configs found in the given folder std::vector m_ConfigMenu; + std::multimap m_ConfigOrders; std::map m_Meters; // The meter windows std::vector m_Themes; diff --git a/Library/System.cpp b/Library/System.cpp index 2f0aeb8f..7c530da7 100644 --- a/Library/System.cpp +++ b/Library/System.cpp @@ -20,22 +20,31 @@ #include "System.h" #include "Litestep.h" #include "Rainmeter.h" +#include "MeasureNet.h" #include "Error.h" +#define DEBUG_VERBOSE (0) // Set 1 if you need verbose logging. + enum TIMER { TIMER_SHOWDESKTOP = 1, - TIMER_COMPOSITION = 2 + TIMER_COMPOSITION = 2, + TIMER_NETSTATS = 3 }; enum INTERVAL { INTERVAL_SHOWDESKTOP = 250, - INTERVAL_COMPOSITION = 250 + INTERVAL_COMPOSITION = 250, + INTERVAL_NETSTATS = 10000 }; MULTIMONITOR_INFO CSystem::c_Monitors = { 0 }; HWND CSystem::c_Window = NULL; +HWND CSystem::c_HelperWindow = NULL; + +HWINEVENTHOOK CSystem::c_WinEventHook = NULL; + bool CSystem::c_DwmCompositionEnabled = false; bool CSystem::c_ShowDesktop = false; @@ -44,7 +53,7 @@ extern CRainmeter* Rainmeter; /* ** Initialize ** -** Creates a window to detect changes in the system. +** Creates a helper window to detect changes in the system. ** */ void CSystem::Initialize(HINSTANCE instance) @@ -59,7 +68,7 @@ void CSystem::Initialize(HINSTANCE instance) c_Window = CreateWindowEx( WS_EX_TOOLWINDOW, L"RainmeterSystemClass", - NULL, + L"SystemWindow", WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, @@ -70,19 +79,43 @@ void CSystem::Initialize(HINSTANCE instance) instance, NULL); - SetWindowPos(c_Window, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + c_HelperWindow = CreateWindowEx( + WS_EX_TOOLWINDOW, + L"RainmeterSystemClass", + L"PositioningHelperWindow", + WS_POPUP, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + NULL, + NULL, + instance, + NULL); #ifndef _WIN64 SetWindowLong(c_Window, GWL_USERDATA, magicDWord); + SetWindowLong(c_HelperWindow, GWL_USERDATA, magicDWord); #endif + SetWindowPos(c_Window, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + SetWindowPos(c_HelperWindow, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + SetMultiMonitorInfo(); c_DwmCompositionEnabled = (DwmIsCompositionEnabled() == TRUE); - if (c_DwmCompositionEnabled) - { - SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_SHOWDESKTOP, NULL); - } + + c_WinEventHook = SetWinEventHook( + EVENT_SYSTEM_FOREGROUND, + EVENT_SYSTEM_FOREGROUND, + NULL, + MyWinEventProc, + 0, + 0, + WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); + + SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_SHOWDESKTOP, NULL); + SetTimer(c_Window, TIMER_NETSTATS, INTERVAL_NETSTATS, NULL); } /* @@ -95,7 +128,11 @@ void CSystem::Finalize() { KillTimer(c_Window, TIMER_SHOWDESKTOP); KillTimer(c_Window, TIMER_COMPOSITION); + KillTimer(c_Window, TIMER_NETSTATS); + if (c_WinEventHook) UnhookWinEvent(c_WinEventHook); + + if (c_HelperWindow) DestroyWindow(c_HelperWindow); if (c_Window) DestroyWindow(c_Window); } @@ -491,102 +528,143 @@ void CSystem::UpdateWorkareaInfo() } /* -** GetShellDesktopWindow +** GetDefaultShellWindow ** -** Finds the Shell's desktop window. +** Finds the Default Shell's window. ** */ -HWND CSystem::GetShellDesktopWindow() +HWND CSystem::GetDefaultShellWindow() { - HWND DesktopW = NULL; + HWND ShellW = GetShellWindow(); - HWND hwnd = FindWindow(L"Progman", L"Program Manager"); - if (!hwnd) return NULL; // Default Shell (Explorer) not started - - if (!(hwnd = FindWindowEx(hwnd, NULL, L"SHELLDLL_DefView", L"")) || - !(DesktopW = FindWindowEx(hwnd, NULL, L"SysListView32", L"FolderView"))) // for Windows 7 (with Aero) + if (ShellW) { - HWND WorkerW = NULL; - while (WorkerW = FindWindowEx(NULL, WorkerW, L"WorkerW", L"")) + HWND hwnd = NULL; + while (hwnd = FindWindowEx(NULL, hwnd, L"Progman", NULL)) { - if ((hwnd = FindWindowEx(WorkerW, NULL, L"SHELLDLL_DefView", L"")) && - (DesktopW = FindWindowEx(hwnd, NULL, L"SysListView32", L"FolderView"))) break; + if (hwnd == ShellW) return ShellW; } } - return DesktopW; + return NULL; } /* -** GetWorkerW +** GetShellDesktopWindow ** -** Finds the WorkerW window. -** If the Progman or WorkerW window is not found, this function returns NULL. +** Finds the Shell's desktop window or WorkerW window. +** If the window is not found, this function returns NULL. ** -** In Windows Vista / 7 (without Aero): +** Note for WorkerW: +** +** In Earlier Windows / 7 (without Aero): ** This function returns a topmost window handle which is visible. ** ** In Windows 7 (with Aero): ** This function returns a window handle which has the "SHELLDLL_DefView". ** */ -HWND CSystem::GetWorkerW() +HWND CSystem::GetShellDesktopWindow(bool findWorkerW) { - HWND WorkerW = NULL; + HWND DesktopW = NULL, hwnd; - HWND hwnd = FindWindow(L"Progman", L"Program Manager"); - if (!hwnd) return NULL; // Default Shell (Explorer) not started + HWND ShellW = GetDefaultShellWindow(); + if (!ShellW) return NULL; // Default Shell (Explorer) not running - if ((hwnd = FindWindowEx(hwnd, NULL, L"SHELLDLL_DefView", L"")) && - (hwnd = FindWindowEx(hwnd, NULL, L"SysListView32", L"FolderView"))) // for Windows Vista / 7 (without Aero) + if ((hwnd = FindWindowEx(ShellW, NULL, L"SHELLDLL_DefView", L"")) && + (DesktopW = FindWindowEx(hwnd, NULL, L"SysListView32", NULL))) // In Earlier Windows / 7 (without Aero) { - while (WorkerW = FindWindowEx(NULL, WorkerW, L"WorkerW", L"")) + if (findWorkerW) { - if (IsWindowVisible(WorkerW)) + HWND WorkerW = NULL; + while (WorkerW = FindWindowEx(NULL, WorkerW, L"WorkerW", L"")) { - // Check whether WorkerW covers whole of the screens - WINDOWPLACEMENT wp = {sizeof(WINDOWPLACEMENT)}; - GetWindowPlacement(WorkerW, &wp); + if (IsWindowVisible(WorkerW) && BelongToSameProcess(ShellW, WorkerW)) + { + // Check whether WorkerW covers whole of the screens + WINDOWPLACEMENT wp = {sizeof(WINDOWPLACEMENT)}; + GetWindowPlacement(WorkerW, &wp); - if (wp.rcNormalPosition.left == c_Monitors.vsL && - wp.rcNormalPosition.top == c_Monitors.vsT && - (wp.rcNormalPosition.right - wp.rcNormalPosition.left) == c_Monitors.vsW && - (wp.rcNormalPosition.bottom - wp.rcNormalPosition.top) == c_Monitors.vsH) break; + if (wp.rcNormalPosition.left == c_Monitors.vsL && + wp.rcNormalPosition.top == c_Monitors.vsT && + (wp.rcNormalPosition.right - wp.rcNormalPosition.left) == c_Monitors.vsW && + (wp.rcNormalPosition.bottom - wp.rcNormalPosition.top) == c_Monitors.vsH) + { + return WorkerW; + } + } + } + } + else + { + if (BelongToSameProcess(ShellW, DesktopW)) + { + return DesktopW; } } } - else // for Windows 7 (with Aero) + else // In Windows 7 (with Aero) { + HWND WorkerW = NULL; while (WorkerW = FindWindowEx(NULL, WorkerW, L"WorkerW", L"")) { - if ((hwnd = FindWindowEx(WorkerW, NULL, L"SHELLDLL_DefView", L"")) && - FindWindowEx(hwnd, NULL, L"SysListView32", L"FolderView")) break; + if (BelongToSameProcess(ShellW, WorkerW)) + { + if ((hwnd = FindWindowEx(WorkerW, NULL, L"SHELLDLL_DefView", L"")) && + (DesktopW = FindWindowEx(hwnd, NULL, L"SysListView32", NULL))) + { + if (findWorkerW) + { + return WorkerW; + } + else + { + return DesktopW; + } + } + } } } - return WorkerW; + return NULL; +} + +/* +** BelongToSameProcess +** +** Checks whether the given windows belong to the same process. +** +*/ +bool CSystem::BelongToSameProcess(HWND hwndA, HWND hwndB) +{ + DWORD procAId = 0, procBId = 0; + + GetWindowThreadProcessId(hwndA, &procAId); + GetWindowThreadProcessId(hwndB, &procBId); + + return (procAId == procBId); } /* ** MyEnumWindowsProc ** -** Retrieves the Rainmeter meter window pinned on desktop in Z-order. +** Retrieves the Rainmeter's meter windows in Z-order. ** */ BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lParam) { - bool logging = false; // Set true if you need verbose logging. + bool logging = CRainmeter::GetDebug() && DEBUG_VERBOSE; WCHAR className[128] = {0}; CMeterWindow* Window; if (GetClassName(hwnd, className, 128) > 0 && wcscmp(className, L"RainmeterMeterWindow") == 0 && - Rainmeter && - (Window = Rainmeter->GetMeterWindow(hwnd))) + Rainmeter && (Window = Rainmeter->GetMeterWindow(hwnd))) { - if (Window->GetWindowZPosition() == ZPOSITION_ONDESKTOP) + ZPOSITION zPos = Window->GetWindowZPosition(); + if (zPos == ZPOSITION_ONDESKTOP) { - if (logging) DebugLog(L"+ [%c] 0x%08X : %s (Name: \"%s\")", IsWindowVisible(hwnd) ? L'V' : L'H', hwnd, className, Window->GetSkinName().c_str()); + if (logging) DebugLog(L"+ [%c] 0x%08X : %s (Name: \"%s\", zPos=%i)", IsWindowVisible(hwnd) ? L'V' : L'H', hwnd, className, Window->GetSkinName().c_str(), (int)zPos); if (lParam) { @@ -595,7 +673,7 @@ BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lParam) } else { - if (logging) DebugLog(L"- [%c] 0x%08X : %s (Name: \"%s\")", IsWindowVisible(hwnd) ? L'V' : L'H', hwnd, className, Window->GetSkinName().c_str()); + if (logging) DebugLog(L"- [%c] 0x%08X : %s (Name: \"%s\", zPos=%i)", IsWindowVisible(hwnd) ? L'V' : L'H', hwnd, className, Window->GetSkinName().c_str(), (int)zPos); } } else @@ -616,42 +694,146 @@ void CSystem::ChangeZPosInOrder() { if (Rainmeter) { - bool logging = false; // Set true if you need verbose logging. + bool logging = CRainmeter::GetDebug() && DEBUG_VERBOSE; std::vector windowsInZOrder; - if (logging) LSLog(LOG_DEBUG, L"Rainmeter", L"1: -----"); + if (logging) LSLog(LOG_DEBUG, L"Rainmeter", L"1: ----- BEFORE -----"); - // Retrieve the Rainmeter meter window in Z-order - if (logging) LSLog(LOG_DEBUG, L"Rainmeter", L" [Top-level window]"); + // Retrieve the Rainmeter's meter windows in Z-order EnumWindows(MyEnumWindowsProc, (LPARAM)(&windowsInZOrder)); - HWND DesktopW = GetShellDesktopWindow(); - if (DesktopW) - { - if (logging) LSLog(LOG_DEBUG, L"Rainmeter", L" [Child of Shell's desktop window]"); - EnumChildWindows(DesktopW, MyEnumWindowsProc, (LPARAM)(&windowsInZOrder)); - } - - if (logging) LSLog(LOG_DEBUG, L"Rainmeter", L"2: -----"); - // Reset ZPos in Z-order for (size_t i = 0; i < windowsInZOrder.size(); i++) { - windowsInZOrder[i]->ChangeZPos(ZPOSITION_ONDESKTOP); // reset + windowsInZOrder[i]->ChangeZPos(windowsInZOrder[i]->GetWindowZPosition()); // reset } if (logging) { - LSLog(LOG_DEBUG, L"Rainmeter", L"3: -----"); - LSLog(LOG_DEBUG, L"Rainmeter", L" [Top-level window]"); + LSLog(LOG_DEBUG, L"Rainmeter", L"2: ----- AFTER -----"); // Log all windows in Z-order EnumWindows(MyEnumWindowsProc, (LPARAM)NULL); + } + } +} - if (DesktopW) +/* +** PrepareHelperWindow +** +** Moves the helper window to the reference position. +** +*/ +void CSystem::PrepareHelperWindow(HWND WorkerW) +{ + bool logging = CRainmeter::GetDebug(); + + if (c_ShowDesktop && WorkerW) + { + // Set WS_EX_TOPMOST flag + SetWindowPos(c_HelperWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + + // Find the "backmost" topmost window + HWND hwnd = WorkerW; + while (hwnd = ::GetNextWindow(hwnd, GW_HWNDPREV)) + { + if (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) { - LSLog(LOG_DEBUG, L"Rainmeter", L" [Child of Shell's desktop window]"); - EnumChildWindows(DesktopW, MyEnumWindowsProc, (LPARAM)NULL); + WCHAR className[128], windowText[128]; + + if (logging) + { + GetClassName(hwnd, className, 128); + GetWindowText(hwnd, windowText, 128); + } + + // Insert the helper window after the found window + if (0 != SetWindowPos(c_HelperWindow, hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING)) + { + if (logging) + { + DebugLog(L"System: HelperWindow: hwnd=0x%08X (WorkerW=0x%08X), hwndInsertAfter=0x%08X (\"%s\" %s) - %s", + c_HelperWindow, WorkerW, hwnd, windowText, className, (GetWindowLong(c_HelperWindow, GWL_EXSTYLE) & WS_EX_TOPMOST) ? L"TOPMOST" : L"NORMAL"); + } + return; + } + + if (logging) + { + DebugLog(L"System: HelperWindow: hwnd=0x%08X (WorkerW=0x%08X), hwndInsertAfter=0x%08X (\"%s\" %s) - FAILED", + c_HelperWindow, WorkerW, hwnd, windowText, className); + } + } + } + + if (logging) + { + DebugLog(L"System: HelperWindow: hwnd=0x%08X (WorkerW=0x%08X), hwndInsertAfter=HWND_TOPMOST - %s", + c_HelperWindow, WorkerW, (GetWindowLong(c_HelperWindow, GWL_EXSTYLE) & WS_EX_TOPMOST) ? L"TOPMOST" : L"NORMAL"); + } + } + else + { + // Insert the helper window to the bottom + SetWindowPos(c_HelperWindow, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + + if (logging) + { + DebugLog(L"System: HelperWindow: hwnd=0x%08X (WorkerW=0x%08X), hwndInsertAfter=HWND_BOTTOM - %s", + c_HelperWindow, WorkerW, (GetWindowLong(c_HelperWindow, GWL_EXSTYLE) & WS_EX_TOPMOST) ? L"TOPMOST" : L"NORMAL"); + } + } +} + +/* +** CheckDesktopState +** +** Changes the "Show Desktop" state. +** +*/ +void CSystem::CheckDesktopState(HWND WorkerW) +{ + HWND hwnd = NULL; + + if (WorkerW) + { + hwnd = FindWindowEx(NULL, WorkerW, L"RainmeterSystemClass", L"SystemWindow"); + } + + if ((hwnd && !c_ShowDesktop) || (!hwnd && c_ShowDesktop)) // State changed + { + c_ShowDesktop = !c_ShowDesktop; + + if (CRainmeter::GetDebug()) + { + DebugLog(L"System: %s", + c_ShowDesktop ? L"\"Show the desktop\" has been detected." : L"\"Show open windows\" has been detected."); + } + + PrepareHelperWindow(WorkerW); + + ChangeZPosInOrder(); + } +} + +/* +** MyWinEventHook +** +** The event hook procedure +** +*/ +void CALLBACK CSystem::MyWinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime) +{ + if (event == EVENT_SYSTEM_FOREGROUND) + { + if (!c_ShowDesktop) + { + WCHAR className[128]; + if (GetClassName(hwnd, className, 128) > 0 && + wcscmp(className, L"WorkerW") == 0 && + hwnd == GetWorkerW()) + { + CheckDesktopState(hwnd); } } } @@ -667,6 +849,11 @@ LRESULT CALLBACK CSystem::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lP { static int DesktopCompositionCheckCount = 0; + if (uMsg == WM_CREATE || hWnd != c_Window) + { + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } + switch (uMsg) { case WM_WINDOWPOSCHANGING: @@ -677,27 +864,7 @@ LRESULT CALLBACK CSystem::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lP switch (wParam) { case TIMER_SHOWDESKTOP: - { - HWND WorkerW = GetWorkerW(), hwnd = NULL; - - if (WorkerW) - { - hwnd = FindWindowEx(NULL, WorkerW, L"RainmeterSystemClass", L""); - } - - if ((hwnd && !c_ShowDesktop) || (!hwnd && c_ShowDesktop)) - { - c_ShowDesktop = !c_ShowDesktop; - - if (CRainmeter::GetDebug()) - { - DebugLog(L"System: %s", - c_ShowDesktop ? L"\"Show the desktop\" has been detected." : L"\"Show open windows\" has been detected."); - } - - ChangeZPosInOrder(); - } - } + CheckDesktopState(GetWorkerW()); return 0; case TIMER_COMPOSITION: @@ -706,12 +873,16 @@ LRESULT CALLBACK CSystem::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lP { KillTimer(c_Window, TIMER_COMPOSITION); - ChangeZPosInOrder(); + c_WinEventHook = SetWinEventHook( + EVENT_SYSTEM_FOREGROUND, + EVENT_SYSTEM_FOREGROUND, + NULL, + MyWinEventProc, + 0, + 0, + WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); - if (c_DwmCompositionEnabled) - { - SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_SHOWDESKTOP, NULL); - } + SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_SHOWDESKTOP, NULL); } else { @@ -719,6 +890,15 @@ LRESULT CALLBACK CSystem::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lP } } return 0; + + case TIMER_NETSTATS: + CMeasureNet::UpdateIFTable(); + + // Statistics + CMeasureNet::UpdateStats(); + Rainmeter->WriteStats(false); + + return 0; } break; @@ -728,6 +908,12 @@ LRESULT CALLBACK CSystem::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lP KillTimer(c_Window, TIMER_SHOWDESKTOP); KillTimer(c_Window, TIMER_COMPOSITION); + if (c_WinEventHook) + { + UnhookWinEvent(c_WinEventHook); + c_WinEventHook = NULL; + } + c_DwmCompositionEnabled = (DwmIsCompositionEnabled() == TRUE); DesktopCompositionCheckCount = 0; diff --git a/Library/System.h b/Library/System.h index fccaec6c..136666f9 100644 --- a/Library/System.h +++ b/Library/System.h @@ -56,10 +56,14 @@ public: static bool GetDwmCompositionEnabled() { return c_DwmCompositionEnabled; } static bool GetShowDesktop() { return c_ShowDesktop; } - static HWND GetShellDesktopWindow(); - static HWND GetWorkerW(); + static HWND GetShellDesktopWindow(bool findWorkerW = false); + static HWND GetWorkerW() { return GetShellDesktopWindow(true); } + + static HWND GetHelperWindow() { return c_HelperWindow; } + static void PrepareHelperWindow(HWND WorkerW); private: + static void CALLBACK MyWinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime); static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static BOOL DwmIsCompositionEnabled(); @@ -67,9 +71,16 @@ private: static void ClearMultiMonitorInfo() { c_Monitors.monitors.clear(); } static void UpdateWorkareaInfo(); + static HWND GetDefaultShellWindow(); static void ChangeZPosInOrder(); + static void CheckDesktopState(HWND WorkerW); + static bool BelongToSameProcess(HWND hwndA, HWND hwndB); + static HWND c_Window; + static HWND c_HelperWindow; + + static HWINEVENTHOOK c_WinEventHook; static MULTIMONITOR_INFO c_Monitors; // Multi-Monitor info diff --git a/Library/TrayWindow.cpp b/Library/TrayWindow.cpp index c5cfa0b3..b9fbb2d4 100644 --- a/Library/TrayWindow.cpp +++ b/Library/TrayWindow.cpp @@ -77,6 +77,8 @@ CTrayWindow::CTrayWindow(HINSTANCE instance) SetWindowLong(m_Window, GWL_USERDATA, magicDWord); #endif + SetWindowPos(m_Window, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + m_TrayPos = 0; memset(m_TrayValues, 0, sizeof(double) * TRAYICON_SIZE); } @@ -408,11 +410,7 @@ LRESULT CALLBACK CTrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } else if(wParam == ID_CONTEXT_REFRESH) { - // Read skins and settings - Rainmeter->ReloadSettings(); - - // Refresh all - RainmeterRefresh(tray->GetWindow(), NULL); + PostMessage(tray->GetWindow(), WM_DELAYED_REFRESH_ALL, (WPARAM)NULL, (LPARAM)NULL); } else if(wParam == ID_CONTEXT_SHOWLOGFILE) { @@ -625,6 +623,14 @@ LRESULT CALLBACK CTrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } break; + case WM_DELAYED_REFRESH_ALL: + if (Rainmeter) + { + // Refresh all + Rainmeter->RefreshAll(); + } + return 0; + case WM_DESTROY: if (Rainmeter->GetDummyLitestep()) PostQuitMessage(0); break; diff --git a/Library/TrayWindow.h b/Library/TrayWindow.h index 1a7d93e6..5db8dcd6 100644 --- a/Library/TrayWindow.h +++ b/Library/TrayWindow.h @@ -24,6 +24,8 @@ #include #include "Measure.h" +#define WM_DELAYED_REFRESH_ALL WM_APP + 0 + #define WM_NOTIFYICON WM_USER + 101 #define TRAYICON_SIZE 16