diff --git a/Library/MeterWindow.cpp b/Library/MeterWindow.cpp index cd1d3648..4693c033 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 context = m_Parser.ReadString(L"Rainmeter", L"ContextTitle", L""); + if (!context.empty()) + { + context = m_Parser.ReadString(L"Rainmeter", L"ContextAction", L""); + if (!context.empty()) + { + 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""); + } + else + { + WCHAR buffer[128]; + + _snwprintf_s(buffer, _TRUNCATE, L"ContextAction%i", position); + action = m_Parser.ReadString(L"Rainmeter", buffer, L""); + } + + 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..99bf3cea 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 = contextTitle.substr(0, 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, 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, IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i, cTitles[i].c_str()); + } + } + } + } } return skinMenu; 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