diff --git a/Library/Measure.cpp b/Library/Measure.cpp index 6319c62e..94532724 100644 --- a/Library/Measure.cpp +++ b/Library/Measure.cpp @@ -61,7 +61,7 @@ static const double g_TblScale[2][4] = { } }; -const int MEDIAN_SIZE = 7; +const int MEDIAN_SIZE = 3; extern CRainmeter* Rainmeter; @@ -440,32 +440,6 @@ bool CMeasure::Update() if (m_UpdateCounter < m_UpdateDivider) return false; m_UpdateCounter = 0; - // If we're logging the maximum value of the measure, check if - // the new value is greater than the old one, and update if necessary. - if (m_LogMaxValue) - { - if (m_MedianMaxValues.empty()) - { - m_MedianMaxValues.resize(MEDIAN_SIZE, 0); - m_MedianMinValues.resize(MEDIAN_SIZE, 0); - } - - m_MedianMaxValues[m_MedianPos] = m_Value; - m_MedianMinValues[m_MedianPos] = m_Value; - ++m_MedianPos; - m_MedianPos %= MEDIAN_SIZE; - - std::vector medianArray; - - medianArray = m_MedianMaxValues; - std::sort(medianArray.begin(), medianArray.end()); - m_MaxValue = max(m_MaxValue, medianArray[MEDIAN_SIZE / 2]); - - medianArray = m_MedianMinValues; - std::sort(medianArray.begin(), medianArray.end()); - m_MinValue = min(m_MinValue, medianArray[MEDIAN_SIZE / 2]); - } - // Call derived method to update value UpdateValue(); @@ -485,12 +459,33 @@ bool CMeasure::Update() m_AveragePos %= averageValuesSize; // Calculate the average value - m_Value = 0; + double value = 0; for (size_t i = 0; i < averageValuesSize; ++i) { - m_Value += m_AverageValues[i]; + value += m_AverageValues[i]; } - m_Value /= (double)averageValuesSize; + m_Value = value / (double)averageValuesSize; + } + + // If we're logging the maximum value of the measure, check if + // the new value is greater than the old one, and update if necessary. + if (m_LogMaxValue) + { + if (m_MedianValues.empty()) + { + m_MedianValues.resize(MEDIAN_SIZE, 0); + } + + m_MedianValues[m_MedianPos] = m_Value; + ++m_MedianPos; + m_MedianPos %= MEDIAN_SIZE; + + auto medianArray = m_MedianValues; + std::sort(&medianArray.data()[0], &medianArray.data()[MEDIAN_SIZE]); // Workaround for "Debug" build mode + + double medianValue = medianArray[MEDIAN_SIZE / 2]; + m_MaxValue = max(m_MaxValue, medianValue); + m_MinValue = min(m_MinValue, medianValue); } if (m_MeterWindow) diff --git a/Library/Measure.h b/Library/Measure.h index c42c4210..db6edc86 100644 --- a/Library/Measure.h +++ b/Library/Measure.h @@ -91,8 +91,7 @@ protected: std::vector m_Substitute; // Vec of substitute strings bool m_RegExpSubstitute; - std::vector m_MedianMaxValues; // The values for the median filtering - std::vector m_MedianMinValues; // The values for the median filtering + std::vector m_MedianValues; // The values for the median filtering UINT m_MedianPos; // Position in the median array, where the new value is placed std::vector m_AverageValues; diff --git a/Library/MeasureNet.cpp b/Library/MeasureNet.cpp index 7c5b7472..eb90a64e 100644 --- a/Library/MeasureNet.cpp +++ b/Library/MeasureNet.cpp @@ -450,14 +450,19 @@ void CMeasureNet::ReadOptions(CConfigParser& parser, const WCHAR* section, NET n Rainmeter->SetNetworkStatisticsTimer(); } - if (maxValue == 0) + if (maxValue == 0.0) { - m_MaxValue = 1; - m_LogMaxValue = true; + if (!m_LogMaxValue) + { + m_MaxValue = 1.0; + m_LogMaxValue = true; + m_MedianValues.clear(); + } } else { m_MaxValue = maxValue / 8; + m_LogMaxValue = false; } } diff --git a/Library/MeasurePlugin.cpp b/Library/MeasurePlugin.cpp index fb3186df..88887f4d 100644 --- a/Library/MeasurePlugin.cpp +++ b/Library/MeasurePlugin.cpp @@ -193,14 +193,12 @@ void CMeasurePlugin::ReadOptions(CConfigParser& parser, const WCHAR* section) { m_MaxValue = 1.0; m_LogMaxValue = true; - - // Plugin options changed, so reset - m_MedianMaxValues.clear(); - m_MedianMinValues.clear(); + m_MedianValues.clear(); } else { m_MaxValue = maxValue; + m_LogMaxValue = false; } } diff --git a/Library/MeterWindow.cpp b/Library/MeterWindow.cpp index cd1d3648..5a4e89cd 100644 --- a/Library/MeterWindow.cpp +++ b/Library/MeterWindow.cpp @@ -140,7 +140,8 @@ CMeterWindow::CMeterWindow(const std::wstring& folderPath, const std::wstring& f m_UpdateCounter(), m_MouseMoveCounter(), m_FontCollection(), - m_ToolTipHidden(false) + m_ToolTipHidden(false), + m_HasCustomContextMenu(false) { if (!c_DwmInstance && CSystem::GetOSPlatform() >= OSPLATFORM_VISTA) { @@ -1925,6 +1926,16 @@ bool CMeterWindow::ReadSkin() // Read options from Rainmeter.ini. ReadOptions(); + std::wstring cTitle = m_Parser.ReadString(L"Rainmeter", L"ContextTitle", L""); + if (!cTitle.empty()) + { + std::wstring cAction = m_Parser.ReadString(L"Rainmeter", L"ContextAction", L""); + if (!cAction.empty() || _wcsicmp(cTitle.c_str(), L"SEPARATOR") == 0) + { + m_HasCustomContextMenu = true; + } + } + // Check the version UINT appVersion = m_Parser.ReadUInt(L"Rainmeter", L"AppVersion", 0); if (appVersion > RAINMETER_VERSION) @@ -3326,6 +3337,28 @@ LRESULT CMeterWindow::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam) WriteOptions(OPTION_POSITION | OPTION_AUTOSELECTSCREEN); } } + else if (wParam >= IDM_SKIN_CUSTOMCONTEXTMENU_FIRST && wParam <= IDM_SKIN_CUSTOMCONTEXTMENU_LAST) + { + std::wstring action; + + int position = (int)wParam - IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + 1; + if (position == 1) + { + action = m_Parser.ReadString(L"Rainmeter", L"ContextAction", L"", false); + } + else + { + WCHAR buffer[128]; + + _snwprintf_s(buffer, _TRUNCATE, L"ContextAction%i", position); + action = m_Parser.ReadString(L"Rainmeter", buffer, L"", false); + } + + if (!action.empty()) + { + Rainmeter->ExecuteCommand(action.c_str(), this); + } + } else { // Forward to tray window, which handles all the other commands diff --git a/Library/MeterWindow.h b/Library/MeterWindow.h index b673ca4d..3f85e0c5 100644 --- a/Library/MeterWindow.h +++ b/Library/MeterWindow.h @@ -234,6 +234,8 @@ public: bool GetMeterToolTipHidden() { return m_ToolTipHidden; } + bool HasCustomContextMenu() { return m_HasCustomContextMenu; } + const CMouse& GetMouse() { return m_Mouse; } void MakePathAbsolute(std::wstring& path); @@ -432,6 +434,8 @@ private: bool m_ToolTipHidden; + bool m_HasCustomContextMenu; + static int c_InstanceCount; static HINSTANCE c_DwmInstance; diff --git a/Library/Rainmeter.cpp b/Library/Rainmeter.cpp index d79ce256..128655ac 100644 --- a/Library/Rainmeter.cpp +++ b/Library/Rainmeter.cpp @@ -2862,8 +2862,9 @@ void CRainmeter::ShowContextMenu(POINT pos, CMeterWindow* meterWindow) WCHAR buffer[256]; GetMenuString(menu, 0, buffer, 256, MF_BYPOSITION); - InsertMenu(subMenu, 11, MF_BYPOSITION | MF_POPUP, (UINT_PTR)rainmeterMenu, buffer); - InsertMenu(subMenu, 12, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + + InsertMenu(subMenu, IDM_CLOSESKIN, MF_BYCOMMAND | MF_POPUP, (UINT_PTR)rainmeterMenu, buffer); + InsertMenu(subMenu, IDM_CLOSESKIN, MF_BYCOMMAND | MF_SEPARATOR, 0, NULL); } else { @@ -3158,6 +3159,69 @@ HMENU CRainmeter::CreateSkinMenu(CMeterWindow* meterWindow, int index, HMENU men } } } + + // Add custom actions to the context menu + if (meterWindow->HasCustomContextMenu()) + { + // Read context menu titles (also read the actions) + std::vector cTitles; + std::wstring contextTitle = meterWindow->GetParser().ReadString(L"Rainmeter", L"ContextTitle", L""); + std::wstring contextAction = meterWindow->GetParser().ReadString(L"Rainmeter", L"ContextAction", L""); + WCHAR buffer[128]; + int i = 1; + + while (!contextTitle.empty() && + (!contextAction.empty() || _wcsicmp(contextTitle.c_str(), L"SEPARATOR") == 0) && + (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i - 1) <= IDM_SKIN_CUSTOMCONTEXTMENU_LAST) // Set maximum context items in resource.h + { + // Trim long titles + if (contextTitle.size() > 30) + { + contextTitle.replace(27, contextTitle.size() - 27, L"..."); + } + + cTitles.push_back(contextTitle); + + _snwprintf_s(buffer, _TRUNCATE, L"ContextTitle%i", ++i); + contextTitle = meterWindow->GetParser().ReadString(L"Rainmeter", buffer, L""); + _snwprintf_s(buffer, _TRUNCATE, L"ContextAction%i", i); + contextAction = meterWindow->GetParser().ReadString(L"Rainmeter", buffer, L""); + } + + // Build a sub-menu if more than one item + size_t titleSize = cTitles.size(); + if (titleSize <= 3) + { + for (size_t i = 0; i < titleSize; ++i) + { + if (_wcsicmp(cTitles[i].c_str(), L"SEPARATOR") == 0) + { + InsertMenu(skinMenu, i + 1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + } + else + { + InsertMenu(skinMenu, i + 1, MF_BYPOSITION | MF_STRING, (index << 16) | (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i), cTitles[i].c_str()); + } + } + } + else + { + HMENU customMenu = CreatePopupMenu(); + InsertMenu(skinMenu, 1, MF_BYPOSITION | MF_POPUP, (UINT_PTR)customMenu, L"Skin Actions"); + + for (size_t i = 0; i < titleSize; ++i) + { + if (_wcsicmp(cTitles[i].c_str(), L"SEPARATOR") == 0) + { + AppendMenu(customMenu, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + } + else + { + AppendMenu(customMenu, MF_BYPOSITION | MF_STRING, (index << 16) | (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i), cTitles[i].c_str()); + } + } + } + } } return skinMenu; @@ -3225,22 +3289,29 @@ void CRainmeter::CreateMonitorMenu(HMENU monitorMenu, CMeterWindow* meterWindow) void CRainmeter::ChangeSkinIndex(HMENU menu, int index) { - int count = GetMenuItemCount(menu); - - for (int i = 0; i < count; ++i) + if (index > 0) { - HMENU subMenu = GetSubMenu(menu, i); - if (subMenu) + int count = GetMenuItemCount(menu); + + for (int i = 0; i < count; ++i) { - ChangeSkinIndex(subMenu, index); - } - else - { - WCHAR buffer[256]; - GetMenuString(menu, i, buffer, 256, MF_BYPOSITION); - UINT id = GetMenuItemID(menu, i); - UINT flags = GetMenuState(menu, i, MF_BYPOSITION); - ModifyMenu(menu, i, MF_BYPOSITION | flags, id | (index << 16), buffer); + HMENU subMenu = GetSubMenu(menu, i); + if (subMenu) + { + ChangeSkinIndex(subMenu, index); + } + else + { + MENUITEMINFO mii = {sizeof(MENUITEMINFO)}; + mii.fMask = MIIM_FTYPE | MIIM_ID; + GetMenuItemInfo(menu, i, TRUE, &mii); + if ((mii.fType & MFT_SEPARATOR) == 0) + { + mii.wID |= (index << 16); + mii.fMask = MIIM_ID; + SetMenuItemInfo(menu, i, TRUE, &mii); + } + } } } } diff --git a/Library/TrayWindow.cpp b/Library/TrayWindow.cpp index 31b84e06..2fe22869 100644 --- a/Library/TrayWindow.cpp +++ b/Library/TrayWindow.cpp @@ -509,41 +509,46 @@ LRESULT CALLBACK CTrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA { Rainmeter->OpenSkinFolder(); } - else if ((wParam & 0x0ffff) >= ID_THEME_FIRST && (wParam & 0x0ffff) <= ID_THEME_LAST) - { - int pos = (wParam & 0x0ffff) - ID_THEME_FIRST; - - const std::vector& layouts = Rainmeter->GetAllLayouts(); - if (pos >= 0 && pos < (int)layouts.size()) - { - Rainmeter->LoadLayout(layouts[pos]); - } - } - else if ((wParam & 0x0ffff) >= ID_CONFIG_FIRST && (wParam & 0x0ffff) <= ID_CONFIG_LAST) - { - std::pair indexes = Rainmeter->GetMeterWindowIndex((UINT)(wParam & 0x0ffff)); - if (indexes.first != -1 && indexes.second != -1) - { - Rainmeter->ToggleSkin(indexes.first, indexes.second); - } - } else { - // Forward the message to correct window - int index = (int)(wParam >> 16); - const std::map& windows = Rainmeter->GetAllMeterWindows(); + UINT mID = wParam & 0x0FFFF; - if (index < (int)windows.size()) + if (mID >= ID_THEME_FIRST && mID <= ID_THEME_LAST) { - std::map::const_iterator iter = windows.begin(); - for ( ; iter != windows.end(); ++iter) + int pos = mID - ID_THEME_FIRST; + + const std::vector& layouts = Rainmeter->GetAllLayouts(); + if (pos >= 0 && pos < (int)layouts.size()) { - --index; - if (index < 0) + Rainmeter->LoadLayout(layouts[pos]); + } + } + else if (mID >= ID_CONFIG_FIRST && mID <= ID_CONFIG_LAST) + { + std::pair indexes = Rainmeter->GetMeterWindowIndex(mID); + if (indexes.first != -1 && indexes.second != -1) + { + Rainmeter->ToggleSkin(indexes.first, indexes.second); + } + } + else + { + // Forward the message to correct window + int index = (int)(wParam >> 16); + const std::map& windows = Rainmeter->GetAllMeterWindows(); + + if (index < (int)windows.size()) + { + std::map::const_iterator iter = windows.begin(); + for ( ; iter != windows.end(); ++iter) { - CMeterWindow* meterWindow = (*iter).second; - SendMessage(meterWindow->GetWindow(), WM_COMMAND, wParam & 0x0FFFF, NULL); - break; + --index; + if (index < 0) + { + CMeterWindow* meterWindow = (*iter).second; + SendMessage(meterWindow->GetWindow(), WM_COMMAND, mID, NULL); + break; + } } } } diff --git a/Library/resource.h b/Library/resource.h index 9799a487..8300f52c 100644 --- a/Library/resource.h +++ b/Library/resource.h @@ -197,6 +197,9 @@ #define IDM_MANAGESKINSMENU_EDIT 4058 #define IDM_COPY 4059 +#define IDM_SKIN_CUSTOMCONTEXTMENU_FIRST 9000 +#define IDM_SKIN_CUSTOMCONTEXTMENU_LAST 9014 + #define ID_CONFIG_EDIT 30000 #define ID_CONFIG_FIRST 30001 #define ID_CONFIG_LAST 40000