mirror of
				https://github.com/chibicitiberiu/rainmeter-studio.git
				synced 2024-02-24 04:33:31 +00:00 
			
		
		
		
	Move context menu related code into ContextMenu.cpp
This commit is contained in:
		
							
								
								
									
										646
									
								
								Library/ContextMenu.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										646
									
								
								Library/ContextMenu.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,646 @@ | ||||
| /* | ||||
|   Copyright (C) 2013 Rainmeter Team | ||||
|  | ||||
|   This program is free software; you can redistribute it and/or | ||||
|   modify it under the terms of the GNU General Public License | ||||
|   as published by the Free Software Foundation; either version 2 | ||||
|   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 General Public License for more details. | ||||
|  | ||||
|   You should have received a copy of the GNU General Public License | ||||
|   along with this program; if not, write to the Free Software | ||||
|   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. | ||||
| */ | ||||
|  | ||||
| #include "StdAfx.h" | ||||
| #include "../Common/MenuTemplate.h" | ||||
| #include "ContextMenu.h" | ||||
| #include "Rainmeter.h" | ||||
| #include "Litestep.h" | ||||
| #include "MeterWindow.h" | ||||
| #include "System.h" | ||||
| #include "TrayWindow.h" | ||||
| #include "resource.h" | ||||
|  | ||||
| ContextMenu::ContextMenu() : | ||||
| 	m_MenuActive(false) | ||||
| { | ||||
| } | ||||
|  | ||||
| /* | ||||
| ** Opens the context menu in given coordinates. | ||||
| */ | ||||
| void ContextMenu::ShowMenu(POINT pos, MeterWindow* meterWindow) | ||||
| { | ||||
| 	static const MenuTemplate s_Menu[] = | ||||
| 	{ | ||||
| 		MENU_ITEM(IDM_MANAGE, ID_STR_MANAGE), | ||||
| 		MENU_ITEM(IDM_ABOUT, ID_STR_ABOUT), | ||||
| 		MENU_ITEM(IDM_SHOW_HELP, ID_STR_HELP), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_SUBMENU(ID_STR_SKINS, | ||||
| 			MENU_ITEM_GRAYED(0, ID_STR_NOSKINS), | ||||
| 			MENU_SEPARATOR(), | ||||
| 			MENU_ITEM(IDM_OPENSKINSFOLDER, ID_STR_OPENFOLDER), | ||||
| 			MENU_ITEM(IDM_DISABLEDRAG, ID_STR_DISABLEDRAGGING)), | ||||
| 		MENU_SUBMENU(ID_STR_THEMES, | ||||
| 			MENU_ITEM_GRAYED(0, ID_STR_NOTHEMES)), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_ITEM(IDM_EDITCONFIG, ID_STR_EDITSETTINGS), | ||||
| 		MENU_ITEM(IDM_REFRESH, ID_STR_REFRESHALL), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_SUBMENU(ID_STR_LOGGING, | ||||
| 			MENU_ITEM(IDM_SHOWLOGFILE, ID_STR_SHOWLOGFILE), | ||||
| 			MENU_SEPARATOR(), | ||||
| 			MENU_ITEM(IDM_STARTLOG, ID_STR_STARTLOGGING), | ||||
| 			MENU_ITEM(IDM_STOPLOG, ID_STR_STOPLOGGING), | ||||
| 			MENU_SEPARATOR(), | ||||
| 			MENU_ITEM(IDM_DELETELOGFILE, ID_STR_DELETELOGFILE), | ||||
| 			MENU_ITEM(IDM_DEBUGLOG, ID_STR_DEBUGMODE)), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_ITEM(IDM_QUIT, ID_STR_EXIT) | ||||
| 	}; | ||||
|  | ||||
| 	if (m_MenuActive || (meterWindow && meterWindow->IsClosing())) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	Rainmeter& rainmeter = GetRainmeter(); | ||||
|  | ||||
| 	m_MenuActive = true; | ||||
|  | ||||
| 	// Show context menu, if no actions were executed | ||||
| 	HMENU menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); | ||||
| 	if (menu) | ||||
| 	{ | ||||
| 		SetMenuDefaultItem(menu, IDM_MANAGE, MF_BYCOMMAND); | ||||
|  | ||||
| 		if (_waccess(GetLogger().GetLogFilePath().c_str(), 0) == -1) | ||||
| 		{ | ||||
| 			EnableMenuItem(menu, IDM_SHOWLOGFILE, MF_BYCOMMAND | MF_GRAYED); | ||||
| 			EnableMenuItem(menu, IDM_DELETELOGFILE, MF_BYCOMMAND | MF_GRAYED); | ||||
| 			EnableMenuItem(menu, IDM_STOPLOG, MF_BYCOMMAND | MF_GRAYED); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			EnableMenuItem( | ||||
| 				menu, | ||||
| 				(GetLogger().IsLogToFile()) ? IDM_STARTLOG : IDM_STOPLOG, | ||||
| 				MF_BYCOMMAND | MF_GRAYED); | ||||
| 		} | ||||
|  | ||||
| 		if (rainmeter.m_Debug) | ||||
| 		{ | ||||
| 			CheckMenuItem(menu, IDM_DEBUGLOG, MF_BYCOMMAND | MF_CHECKED); | ||||
| 		} | ||||
|  | ||||
| 		HMENU allSkinsMenu = GetSubMenu(menu, 4); | ||||
| 		if (allSkinsMenu) | ||||
| 		{ | ||||
| 			if (!rainmeter.m_SkinRegistry.IsEmpty()) | ||||
| 			{ | ||||
| 				DeleteMenu(allSkinsMenu, 0, MF_BYPOSITION);  // "No skins available" menuitem | ||||
| 				CreateAllSkinsMenu(allSkinsMenu); | ||||
| 			} | ||||
|  | ||||
| 			if (rainmeter.m_DisableDragging) | ||||
| 			{ | ||||
| 				CheckMenuItem(allSkinsMenu, IDM_DISABLEDRAG, MF_BYCOMMAND | MF_CHECKED); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		HMENU layoutMenu = GetSubMenu(menu, 5); | ||||
| 		if (layoutMenu) | ||||
| 		{ | ||||
| 			if (!rainmeter.m_Layouts.empty()) | ||||
| 			{ | ||||
| 				DeleteMenu(layoutMenu, 0, MF_BYPOSITION);  // "No layouts available" menuitem | ||||
| 				CreateLayoutMenu(layoutMenu); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (meterWindow) | ||||
| 		{ | ||||
| 			HMENU rainmeterMenu = menu; | ||||
| 			menu = CreateSkinMenu(meterWindow, 0, allSkinsMenu); | ||||
|  | ||||
| 			InsertMenu(menu, IDM_CLOSESKIN, MF_BYCOMMAND | MF_POPUP, (UINT_PTR)rainmeterMenu, L"Rainmeter"); | ||||
| 			InsertMenu(menu, IDM_CLOSESKIN, MF_BYCOMMAND | MF_SEPARATOR, 0, nullptr); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			InsertMenu(menu, 12, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); | ||||
|  | ||||
| 			// Create a menu for all active skins | ||||
| 			int index = 0; | ||||
| 			std::map<std::wstring, MeterWindow*>::const_iterator iter = rainmeter.m_MeterWindows.begin(); | ||||
| 			for (; iter != rainmeter.m_MeterWindows.end(); ++iter) | ||||
| 			{ | ||||
| 				MeterWindow* mw = ((*iter).second); | ||||
| 				HMENU skinMenu = CreateSkinMenu(mw, index, allSkinsMenu); | ||||
| 				InsertMenu(menu, 12, MF_BYPOSITION | MF_POPUP, (UINT_PTR)skinMenu, mw->GetFolderPath().c_str()); | ||||
| 				++index; | ||||
| 			} | ||||
|  | ||||
| 			// Add update notification item | ||||
| 			if (rainmeter.m_NewVersion) | ||||
| 			{ | ||||
| 				InsertMenu(menu, 0, MF_BYPOSITION, IDM_NEW_VERSION, GetString(ID_STR_UPDATEAVAILABLE)); | ||||
| 				HiliteMenuItem(rainmeter.GetTrayWindow()->GetWindow(), menu, 0, MF_BYPOSITION | MF_HILITE); | ||||
| 				InsertMenu(menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		HWND hWnd = WindowFromPoint(pos); | ||||
| 		if (hWnd != nullptr) | ||||
| 		{ | ||||
| 			MeterWindow* mw = rainmeter.GetMeterWindow(hWnd); | ||||
| 			if (mw) | ||||
| 			{ | ||||
| 				// Cancel the mouse event beforehand | ||||
| 				mw->SetMouseLeaveEvent(true); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// Set the window to foreground | ||||
| 		hWnd = meterWindow ? meterWindow->GetWindow() : rainmeter.m_TrayWindow->GetWindow(); | ||||
| 		HWND hWndForeground = GetForegroundWindow(); | ||||
| 		if (hWndForeground != hWnd) | ||||
| 		{ | ||||
| 			DWORD foregroundThreadID = GetWindowThreadProcessId(hWndForeground, nullptr); | ||||
| 			DWORD currentThreadID = GetCurrentThreadId(); | ||||
| 			AttachThreadInput(currentThreadID, foregroundThreadID, TRUE); | ||||
| 			SetForegroundWindow(hWnd); | ||||
| 			AttachThreadInput(currentThreadID, foregroundThreadID, FALSE); | ||||
| 		} | ||||
|  | ||||
| 		// Show context menu | ||||
| 		TrackPopupMenu( | ||||
| 			menu, | ||||
| 			TPM_RIGHTBUTTON | TPM_LEFTALIGN | (*GetString(ID_STR_ISRTL) == L'1' ? TPM_LAYOUTRTL : 0), | ||||
| 			pos.x, | ||||
| 			pos.y, | ||||
| 			0, | ||||
| 			hWnd, | ||||
| 			nullptr); | ||||
|  | ||||
| 		if (meterWindow) | ||||
| 		{ | ||||
| 			DestroyMenu(menu); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	DestroyMenu(menu); | ||||
|  | ||||
| 	m_MenuActive = false; | ||||
| } | ||||
|  | ||||
| HMENU ContextMenu::CreateSkinMenu(MeterWindow* meterWindow, int index, HMENU menu) | ||||
| { | ||||
| 	static const MenuTemplate s_Menu[] = | ||||
| 	{ | ||||
| 		MENU_ITEM(IDM_SKIN_OPENSKINSFOLDER, 0), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_SUBMENU(ID_STR_VARIANTS, | ||||
| 			MENU_SEPARATOR()), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_SUBMENU(ID_STR_SETTINGS, | ||||
| 			MENU_SUBMENU(ID_STR_POSITION, | ||||
| 				MENU_SUBMENU(ID_STR_DISPLAYMONITOR, | ||||
| 					MENU_ITEM(IDM_SKIN_MONITOR_PRIMARY, ID_STR_USEDEFAULTMONITOR), | ||||
| 					MENU_ITEM(ID_MONITOR_FIRST, ID_STR_VIRTUALSCREEN), | ||||
| 					MENU_SEPARATOR(), | ||||
| 					MENU_SEPARATOR(), | ||||
| 					MENU_ITEM(IDM_SKIN_MONITOR_AUTOSELECT, ID_STR_AUTOSELECTMONITOR)), | ||||
| 				MENU_SEPARATOR(), | ||||
| 				MENU_ITEM(IDM_SKIN_VERYTOPMOST, ID_STR_STAYTOPMOST), | ||||
| 				MENU_ITEM(IDM_SKIN_TOPMOST, ID_STR_TOPMOST), | ||||
| 				MENU_ITEM(IDM_SKIN_NORMAL, ID_STR_NORMAL), | ||||
| 				MENU_ITEM(IDM_SKIN_BOTTOM, ID_STR_BOTTOM), | ||||
| 				MENU_ITEM(IDM_SKIN_ONDESKTOP, ID_STR_ONDESKTOP), | ||||
| 				MENU_SEPARATOR(), | ||||
| 				MENU_ITEM(IDM_SKIN_FROMRIGHT, ID_STR_FROMRIGHT), | ||||
| 				MENU_ITEM(IDM_SKIN_FROMBOTTOM, ID_STR_FROMBOTTOM), | ||||
| 				MENU_ITEM(IDM_SKIN_XPERCENTAGE, ID_STR_XASPERCENTAGE), | ||||
| 				MENU_ITEM(IDM_SKIN_YPERCENTAGE, ID_STR_YASPERCENTAGE)), | ||||
| 			MENU_SUBMENU(ID_STR_TRANSPARENCY, | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_0, ID_STR_0PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_10, ID_STR_10PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_20, ID_STR_20PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_30, ID_STR_30PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_40, ID_STR_40PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_50, ID_STR_50PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_60, ID_STR_60PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_70, ID_STR_70PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_80, ID_STR_80PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_90, ID_STR_90PERCENT), | ||||
| 				MENU_SEPARATOR(), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_FADEIN, ID_STR_FADEIN), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_FADEOUT, ID_STR_FADEOUT)), | ||||
| 			MENU_SEPARATOR(), | ||||
| 			MENU_ITEM(IDM_SKIN_HIDEONMOUSE, ID_STR_HIDEONMOUSEOVER), | ||||
| 			MENU_ITEM(IDM_SKIN_DRAGGABLE, ID_STR_DRAGGABLE), | ||||
| 			MENU_ITEM(IDM_SKIN_REMEMBERPOSITION, ID_STR_SAVEPOSITION), | ||||
| 			MENU_ITEM(IDM_SKIN_SNAPTOEDGES, ID_STR_SNAPTOEDGES), | ||||
| 			MENU_ITEM(IDM_SKIN_CLICKTHROUGH, ID_STR_CLICKTHROUGH), | ||||
| 			MENU_ITEM(IDM_SKIN_KEEPONSCREEN, ID_STR_KEEPONSCREEN)), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_ITEM(IDM_SKIN_MANAGESKIN, ID_STR_MANAGESKIN), | ||||
| 		MENU_ITEM(IDM_SKIN_EDITSKIN, ID_STR_EDITSKIN), | ||||
| 		MENU_ITEM(IDM_SKIN_REFRESH, ID_STR_REFRESHSKIN), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_ITEM(IDM_CLOSESKIN, ID_STR_UNLOADSKIN) | ||||
| 	}; | ||||
|  | ||||
| 	HMENU skinMenu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); | ||||
| 	if (skinMenu) | ||||
| 	{ | ||||
| 		// Tick the position | ||||
| 		HMENU settingsMenu = GetSubMenu(skinMenu, 4); | ||||
| 		if (settingsMenu) | ||||
| 		{ | ||||
| 			HMENU posMenu = GetSubMenu(settingsMenu, 0); | ||||
| 			if (posMenu) | ||||
| 			{ | ||||
| 				UINT checkPos = IDM_SKIN_NORMAL - (UINT)meterWindow->GetWindowZPosition(); | ||||
| 				CheckMenuRadioItem(posMenu, checkPos, checkPos, checkPos, MF_BYCOMMAND); | ||||
|  | ||||
| 				if (meterWindow->GetXFromRight()) CheckMenuItem(posMenu, IDM_SKIN_FROMRIGHT, MF_BYCOMMAND | MF_CHECKED); | ||||
| 				if (meterWindow->GetYFromBottom()) CheckMenuItem(posMenu, IDM_SKIN_FROMBOTTOM, MF_BYCOMMAND | MF_CHECKED); | ||||
| 				if (meterWindow->GetXPercentage()) CheckMenuItem(posMenu, IDM_SKIN_XPERCENTAGE, MF_BYCOMMAND | MF_CHECKED); | ||||
| 				if (meterWindow->GetYPercentage()) CheckMenuItem(posMenu, IDM_SKIN_YPERCENTAGE, MF_BYCOMMAND | MF_CHECKED); | ||||
|  | ||||
| 				HMENU monitorMenu = GetSubMenu(posMenu, 0); | ||||
| 				if (monitorMenu) | ||||
| 				{ | ||||
| 					CreateMonitorMenu(monitorMenu, meterWindow); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// Tick the transparency | ||||
| 			HMENU alphaMenu = GetSubMenu(settingsMenu, 1); | ||||
| 			if (alphaMenu) | ||||
| 			{ | ||||
| 				UINT checkPos = (UINT)(10 - meterWindow->GetAlphaValue() / 25.5); | ||||
| 				checkPos = min(9, checkPos); | ||||
| 				checkPos = max(0, checkPos); | ||||
| 				CheckMenuRadioItem(alphaMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); | ||||
|  | ||||
| 				switch (meterWindow->GetWindowHide()) | ||||
| 				{ | ||||
| 				case HIDEMODE_FADEIN: | ||||
| 					CheckMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_CHECKED); | ||||
| 					EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_GRAYED); | ||||
| 					break; | ||||
|  | ||||
| 				case HIDEMODE_FADEOUT: | ||||
| 					CheckMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_CHECKED); | ||||
| 					EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_GRAYED); | ||||
| 					break; | ||||
|  | ||||
| 				case HIDEMODE_HIDE: | ||||
| 					EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_GRAYED); | ||||
| 					EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_GRAYED); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// Tick the settings | ||||
| 			switch (meterWindow->GetWindowHide()) | ||||
| 			{ | ||||
| 			case HIDEMODE_HIDE: | ||||
| 				CheckMenuItem(settingsMenu, IDM_SKIN_HIDEONMOUSE, MF_BYCOMMAND | MF_CHECKED); | ||||
| 				break; | ||||
|  | ||||
| 			case HIDEMODE_FADEIN: | ||||
| 			case HIDEMODE_FADEOUT: | ||||
| 				EnableMenuItem(settingsMenu, IDM_SKIN_HIDEONMOUSE, MF_BYCOMMAND | MF_GRAYED); | ||||
| 				break; | ||||
| 			} | ||||
|  | ||||
| 			if (meterWindow->GetSnapEdges()) | ||||
| 			{ | ||||
| 				CheckMenuItem(settingsMenu, IDM_SKIN_SNAPTOEDGES, MF_BYCOMMAND | MF_CHECKED); | ||||
| 			} | ||||
|  | ||||
| 			if (meterWindow->GetSavePosition()) | ||||
| 			{ | ||||
| 				CheckMenuItem(settingsMenu, IDM_SKIN_REMEMBERPOSITION, MF_BYCOMMAND | MF_CHECKED); | ||||
| 			} | ||||
|  | ||||
| 			if (GetRainmeter().m_DisableDragging) | ||||
| 			{ | ||||
| 				EnableMenuItem(settingsMenu, IDM_SKIN_DRAGGABLE, MF_BYCOMMAND | MF_GRAYED); | ||||
| 			} | ||||
| 			else if (meterWindow->GetWindowDraggable()) | ||||
| 			{ | ||||
| 				CheckMenuItem(settingsMenu, IDM_SKIN_DRAGGABLE, MF_BYCOMMAND | MF_CHECKED); | ||||
| 			} | ||||
|  | ||||
| 			if (meterWindow->GetClickThrough()) | ||||
| 			{ | ||||
| 				CheckMenuItem(settingsMenu, IDM_SKIN_CLICKTHROUGH, MF_BYCOMMAND | MF_CHECKED); | ||||
| 			} | ||||
|  | ||||
| 			if (meterWindow->GetKeepOnScreen()) | ||||
| 			{ | ||||
| 				CheckMenuItem(settingsMenu, IDM_SKIN_KEEPONSCREEN, MF_BYCOMMAND | MF_CHECKED); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// Add the name of the Skin to the menu | ||||
| 		const std::wstring& skinName = meterWindow->GetFolderPath(); | ||||
| 		ModifyMenu(skinMenu, IDM_SKIN_OPENSKINSFOLDER, MF_BYCOMMAND, IDM_SKIN_OPENSKINSFOLDER, skinName.c_str()); | ||||
| 		SetMenuDefaultItem(skinMenu, IDM_SKIN_OPENSKINSFOLDER, FALSE); | ||||
|  | ||||
| 		// Remove dummy menuitem from the variants menu | ||||
| 		HMENU variantsMenu = GetSubMenu(skinMenu, 2); | ||||
| 		if (variantsMenu) | ||||
| 		{ | ||||
| 			DeleteMenu(variantsMenu, 0, MF_BYPOSITION); | ||||
| 		} | ||||
|  | ||||
| 		// Give the menuitem the unique id that depends on the skin | ||||
| 		ChangeSkinIndex(skinMenu, index); | ||||
|  | ||||
| 		// Add the variants menu | ||||
| 		if (variantsMenu) | ||||
| 		{ | ||||
| 			const SkinRegistry::Folder& skinFolder = *GetRainmeter().m_SkinRegistry.FindFolder(skinName); | ||||
| 			for (int i = 0, isize = (int)skinFolder.files.size(); i < isize; ++i) | ||||
| 			{ | ||||
| 				InsertMenu(variantsMenu, i, MF_BYPOSITION, skinFolder.baseID + i, skinFolder.files[i].c_str()); | ||||
| 			} | ||||
|  | ||||
| 			if (skinFolder.active) | ||||
| 			{ | ||||
| 				UINT checkPos = skinFolder.active - 1; | ||||
| 				CheckMenuRadioItem(variantsMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// Add skin root menu | ||||
| 		int itemCount = GetMenuItemCount(menu); | ||||
| 		if (itemCount > 0) | ||||
| 		{ | ||||
| 			std::wstring root = meterWindow->GetFolderPath(); | ||||
| 			std::wstring::size_type pos = root.find_first_of(L'\\'); | ||||
| 			if (pos != std::wstring::npos) | ||||
| 			{ | ||||
| 				root.erase(pos); | ||||
| 			} | ||||
|  | ||||
| 			for (int i = 0; i < itemCount; ++i) | ||||
| 			{ | ||||
| 				UINT state = GetMenuState(menu, i, MF_BYPOSITION); | ||||
| 				if (state == 0xFFFFFFFF || (state & MF_POPUP) == 0) break; | ||||
|  | ||||
| 				WCHAR buffer[MAX_PATH]; | ||||
| 				if (GetMenuString(menu, i, buffer, MAX_PATH, MF_BYPOSITION)) | ||||
| 				{ | ||||
| 					if (_wcsicmp(root.c_str(), buffer) == 0) | ||||
| 					{ | ||||
| 						HMENU skinRootMenu = GetSubMenu(menu, i); | ||||
| 						if (skinRootMenu) | ||||
| 						{ | ||||
| 							InsertMenu(skinMenu, 3, MF_BYPOSITION | MF_POPUP, (UINT_PTR)skinRootMenu, root.c_str()); | ||||
| 						} | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// Add custom actions to the context menu | ||||
| 		std::wstring contextTitle = meterWindow->GetParser().ReadString(L"Rainmeter", L"ContextTitle", L""); | ||||
| 		if (!contextTitle.empty()) | ||||
| 		{ | ||||
| 			auto isTitleSeparator = [](const std::wstring& title) | ||||
| 			{ | ||||
| 				return title.find_first_not_of(L'-') == std::wstring::npos; | ||||
| 			}; | ||||
|  | ||||
| 			std::wstring contextAction = meterWindow->GetParser().ReadString(L"Rainmeter", L"ContextAction", L""); | ||||
| 			if (!contextAction.empty() || isTitleSeparator(contextTitle)) | ||||
| 			{ | ||||
| 				std::vector<std::wstring> cTitles; | ||||
| 				WCHAR buffer[128]; | ||||
| 				int i = 1; | ||||
|  | ||||
| 				while (!contextTitle.empty() && | ||||
| 					  (!contextAction.empty() || isTitleSeparator(contextTitle)) && | ||||
| 					  (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 three items | ||||
| 				size_t titleSize = cTitles.size(); | ||||
| 				if (titleSize <= 3) | ||||
| 				{ | ||||
| 					size_t position = 0; | ||||
| 					for (size_t i = 0; i < titleSize; ++i) | ||||
| 					{ | ||||
| 						if (isTitleSeparator(cTitles[i])) | ||||
| 						{ | ||||
| 							// Separators not allowed in main top-level menu | ||||
| 							--position; | ||||
| 						} | ||||
| 						else | ||||
| 						{ | ||||
| 							InsertMenu(skinMenu, position + 1, MF_BYPOSITION | MF_STRING, (index << 16) | (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i), cTitles[i].c_str()); | ||||
| 						} | ||||
|  | ||||
| 						++position; | ||||
| 					} | ||||
|  | ||||
| 					if (position != 0) | ||||
| 					{ | ||||
| 						InsertMenu(skinMenu, 1, MF_BYPOSITION | MF_STRING | MF_GRAYED, 0, L"Custom skin actions"); | ||||
| 						InsertMenu(skinMenu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); | ||||
| 					} | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					HMENU customMenu = CreatePopupMenu(); | ||||
| 					InsertMenu(skinMenu, 1, MF_BYPOSITION | MF_POPUP, (UINT_PTR)customMenu, L"Custom skin actions"); | ||||
| 				 | ||||
| 					for (size_t i = 0; i < titleSize; ++i) | ||||
| 					{ | ||||
| 						if (isTitleSeparator(cTitles[i])) | ||||
| 						{ | ||||
| 							AppendMenu(customMenu, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); | ||||
| 						} | ||||
| 						else | ||||
| 						{ | ||||
| 							AppendMenu(customMenu, MF_BYPOSITION | MF_STRING, (index << 16) | (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i), cTitles[i].c_str()); | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 					InsertMenu(skinMenu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return skinMenu; | ||||
| } | ||||
|  | ||||
| int ContextMenu::CreateAllSkinsMenuRecursive(HMENU skinMenu, int index) | ||||
| { | ||||
| 	SkinRegistry& skinRegistry = GetRainmeter().m_SkinRegistry; | ||||
| 	const int initialLevel = skinRegistry.GetFolder(index).level; | ||||
| 	int menuIndex = 0; | ||||
|  | ||||
| 	const size_t max = skinRegistry.GetFolderCount(); | ||||
| 	while (index < max) | ||||
| 	{ | ||||
| 		const SkinRegistry::Folder& skinFolder = skinRegistry.GetFolder(index); | ||||
| 		if (skinFolder.level != initialLevel) | ||||
| 		{ | ||||
| 			return index - 1; | ||||
| 		} | ||||
|  | ||||
| 		HMENU subMenu = CreatePopupMenu(); | ||||
|  | ||||
| 		// Add current folder | ||||
| 		InsertMenu(skinMenu, menuIndex, MF_POPUP | MF_BYPOSITION, (UINT_PTR)subMenu, skinFolder.name.c_str()); | ||||
|  | ||||
| 		// Add subfolders | ||||
| 		const bool hasSubfolder = (index + 1) < max && skinRegistry.GetFolder(index + 1).level == initialLevel + 1; | ||||
| 		if (hasSubfolder) | ||||
| 		{ | ||||
| 			index = CreateAllSkinsMenuRecursive(subMenu, index + 1); | ||||
| 		} | ||||
|  | ||||
| 		// Add files | ||||
| 		{ | ||||
| 			int fileIndex = 0; | ||||
| 			int fileCount = (int)skinFolder.files.size(); | ||||
| 			for ( ; fileIndex < fileCount; ++fileIndex) | ||||
| 			{ | ||||
| 				InsertMenu(subMenu, fileIndex, MF_STRING | MF_BYPOSITION, skinFolder.baseID + fileIndex, skinFolder.files[fileIndex].c_str()); | ||||
| 			} | ||||
|  | ||||
| 			if (skinFolder.active) | ||||
| 			{ | ||||
| 				UINT checkPos = skinFolder.active - 1; | ||||
| 				CheckMenuRadioItem(subMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); | ||||
| 			} | ||||
|  | ||||
| 			if (hasSubfolder && fileIndex != 0) | ||||
| 			{ | ||||
| 				InsertMenu(subMenu, fileIndex, MF_SEPARATOR | MF_BYPOSITION, 0, nullptr); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		++menuIndex; | ||||
| 		++index; | ||||
| 	} | ||||
|  | ||||
| 	return index; | ||||
| } | ||||
|  | ||||
| void ContextMenu::CreateLayoutMenu(HMENU layoutMenu) | ||||
| { | ||||
| 	const auto& layouts = GetRainmeter().m_Layouts; | ||||
| 	for (size_t i = 0, isize = layouts.size(); i < isize; ++i) | ||||
| 	{ | ||||
| 		InsertMenu(layoutMenu, i, MF_BYPOSITION, ID_THEME_FIRST + i, layouts[i].c_str()); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void ContextMenu::CreateMonitorMenu(HMENU monitorMenu, MeterWindow* meterWindow) | ||||
| { | ||||
| 	bool screenDefined = meterWindow->GetXScreenDefined(); | ||||
| 	int screenIndex = meterWindow->GetXScreen(); | ||||
|  | ||||
| 	// for the "Specified monitor" (@n) | ||||
| 	const size_t numOfMonitors = System::GetMonitorCount();  // intentional | ||||
| 	const std::vector<MonitorInfo>& monitors = System::GetMultiMonitorInfo().monitors; | ||||
|  | ||||
| 	int i = 1; | ||||
| 	for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter, ++i) | ||||
| 	{ | ||||
| 		WCHAR buffer[64]; | ||||
| 		size_t len = _snwprintf_s(buffer, _TRUNCATE, L"@%i: ", i); | ||||
|  | ||||
| 		std::wstring item(buffer, len); | ||||
|  | ||||
| 		if ((*iter).monitorName.size() > 32) | ||||
| 		{ | ||||
| 			item.append((*iter).monitorName, 0, 32); | ||||
| 			item += L"..."; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			item += (*iter).monitorName; | ||||
| 		} | ||||
|  | ||||
| 		InsertMenu(monitorMenu, | ||||
| 			i + 2, | ||||
| 			MF_BYPOSITION | ((screenDefined && screenIndex == i) ? MF_CHECKED : MF_UNCHECKED) | ((!(*iter).active) ? MF_GRAYED : MF_ENABLED), | ||||
| 			ID_MONITOR_FIRST + i, | ||||
| 			item.c_str()); | ||||
| 	} | ||||
|  | ||||
| 	if (!screenDefined) | ||||
| 	{ | ||||
| 		CheckMenuItem(monitorMenu, IDM_SKIN_MONITOR_PRIMARY, MF_BYCOMMAND | MF_CHECKED); | ||||
| 	} | ||||
|  | ||||
| 	if (screenDefined && screenIndex == 0) | ||||
| 	{ | ||||
| 		CheckMenuItem(monitorMenu, ID_MONITOR_FIRST, MF_BYCOMMAND | MF_CHECKED); | ||||
| 	} | ||||
|  | ||||
| 	if (meterWindow->GetAutoSelectScreen()) | ||||
| 	{ | ||||
| 		CheckMenuItem(monitorMenu, IDM_SKIN_MONITOR_AUTOSELECT, MF_BYCOMMAND | MF_CHECKED); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void ContextMenu::ChangeSkinIndex(HMENU menu, int index) | ||||
| { | ||||
| 	if (index > 0) | ||||
| 	{ | ||||
| 		int count = GetMenuItemCount(menu); | ||||
|  | ||||
| 		for (int i = 0; i < count; ++i) | ||||
| 		{ | ||||
| 			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); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										50
									
								
								Library/ContextMenu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								Library/ContextMenu.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| /* | ||||
|   Copyright (C) 2013 Rainmeter Team | ||||
|  | ||||
|   This program is free software; you can redistribute it and/or | ||||
|   modify it under the terms of the GNU General Public License | ||||
|   as published by the Free Software Foundation; either version 2 | ||||
|   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 General Public License for more details. | ||||
|  | ||||
|   You should have received a copy of the GNU General Public License | ||||
|   along with this program; if not, write to the Free Software | ||||
|   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. | ||||
| */ | ||||
|  | ||||
| #ifndef RM_LIBRARY_CONTEXTMENU_H | ||||
| #define RM_LIBRARY_CONTEXTMENU_H | ||||
|  | ||||
| #include <Windows.h> | ||||
|  | ||||
| class MeterWindow; | ||||
|  | ||||
| // Handles the creation and display of Rainmeter and skin context menus. | ||||
| class ContextMenu | ||||
| { | ||||
| public: | ||||
| 	ContextMenu(); | ||||
|  | ||||
| 	bool IsMenuActive() { return m_MenuActive; } | ||||
|  | ||||
| 	void ShowMenu(POINT pos, MeterWindow* meterWindow); | ||||
|  | ||||
| 	static void CreateMonitorMenu(HMENU monitorMenu, MeterWindow* meterWindow); | ||||
|  | ||||
| private: | ||||
| 	static HMENU CreateSkinMenu(MeterWindow* meterWindow, int index, HMENU menu); | ||||
| 	static void ChangeSkinIndex(HMENU subMenu, int index); | ||||
| 	 | ||||
| 	static void CreateAllSkinsMenu(HMENU skinMenu) { CreateAllSkinsMenuRecursive(skinMenu, 0); } | ||||
| 	static int CreateAllSkinsMenuRecursive(HMENU skinMenu, int index); | ||||
|  | ||||
| 	static void CreateLayoutMenu(HMENU layoutMenu); | ||||
|  | ||||
| 	bool m_MenuActive; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| @@ -1185,7 +1185,7 @@ INT_PTR DialogManage::TabSkins::OnCommand(WPARAM wParam, LPARAM lParam) | ||||
| 			HMENU menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); | ||||
| 			if (menu) | ||||
| 			{ | ||||
| 				GetRainmeter().CreateMonitorMenu(menu, m_SkinWindow); | ||||
| 				ContextMenu::CreateMonitorMenu(menu, m_SkinWindow); | ||||
|  | ||||
| 				RECT r; | ||||
| 				GetWindowRect((HWND)lParam, &r); | ||||
|   | ||||
| @@ -90,6 +90,9 @@ | ||||
|     <ClCompile Include="ConfigParser_Test.cpp"> | ||||
|       <ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="ContextMenu.cpp"> | ||||
|       <PrecompiledHeader>Use</PrecompiledHeader> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="DialogAbout.cpp"> | ||||
|       <PrecompiledHeader>Use</PrecompiledHeader> | ||||
|     </ClCompile> | ||||
| @@ -315,6 +318,7 @@ | ||||
|     <ClInclude Include="..\Common\Gfx\Util\WICBitmapLockGDIP.h" /> | ||||
|     <ClInclude Include="CommandHandler.h" /> | ||||
|     <ClInclude Include="ConfigParser.h" /> | ||||
|     <ClInclude Include="ContextMenu.h" /> | ||||
|     <ClInclude Include="DialogAbout.h" /> | ||||
|     <ClInclude Include="Error.h" /> | ||||
|     <ClInclude Include="Group.h" /> | ||||
|   | ||||
| @@ -387,6 +387,9 @@ | ||||
|     <ClCompile Include="SkinRegistry_Test.cpp"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="ContextMenu.cpp"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClInclude Include="ConfigParser.h"> | ||||
| @@ -662,6 +665,9 @@ | ||||
|     <ClInclude Include="SkinRegistry.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="ContextMenu.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ResourceCompile Include="Library.rc"> | ||||
|   | ||||
| @@ -17,7 +17,6 @@ | ||||
| */ | ||||
|  | ||||
| #include "StdAfx.h" | ||||
| #include "../Common/MenuTemplate.h" | ||||
| #include "../Common/PathUtil.h" | ||||
| #include "Rainmeter.h" | ||||
| #include "TrayWindow.h" | ||||
| @@ -28,7 +27,6 @@ | ||||
| #include "MeasureNet.h" | ||||
| #include "MeasureCPU.h" | ||||
| #include "MeterString.h" | ||||
| #include "resource.h" | ||||
| #include "UpdateCheck.h" | ||||
| #include "../Version.h" | ||||
|  | ||||
| @@ -115,7 +113,6 @@ Rainmeter::Rainmeter() : | ||||
| 	m_DesktopWorkAreaChanged(false), | ||||
| 	m_DesktopWorkAreaType(false), | ||||
| 	m_NormalStayDesktop(true), | ||||
| 	m_MenuActive(false), | ||||
| 	m_DisableRDP(false), | ||||
| 	m_DisableDragging(false), | ||||
| 	m_CurrentParser(), | ||||
| @@ -1708,610 +1705,6 @@ int Rainmeter::ShowMessage(HWND parent, const WCHAR* text, UINT type) | ||||
| 	return MessageBox(parent, text, APPNAME, type); | ||||
| }; | ||||
|  | ||||
| /* | ||||
| ** Opens the context menu in given coordinates. | ||||
| ** | ||||
| */ | ||||
| void Rainmeter::ShowContextMenu(POINT pos, MeterWindow* meterWindow) | ||||
| { | ||||
| 	static const MenuTemplate s_Menu[] = | ||||
| 	{ | ||||
| 		MENU_ITEM(IDM_MANAGE, ID_STR_MANAGE), | ||||
| 		MENU_ITEM(IDM_ABOUT, ID_STR_ABOUT), | ||||
| 		MENU_ITEM(IDM_SHOW_HELP, ID_STR_HELP), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_SUBMENU(ID_STR_SKINS, | ||||
| 			MENU_ITEM_GRAYED(0, ID_STR_NOSKINS), | ||||
| 			MENU_SEPARATOR(), | ||||
| 			MENU_ITEM(IDM_OPENSKINSFOLDER, ID_STR_OPENFOLDER), | ||||
| 			MENU_ITEM(IDM_DISABLEDRAG, ID_STR_DISABLEDRAGGING)), | ||||
| 		MENU_SUBMENU(ID_STR_THEMES, | ||||
| 			MENU_ITEM_GRAYED(0, ID_STR_NOTHEMES)), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_ITEM(IDM_EDITCONFIG, ID_STR_EDITSETTINGS), | ||||
| 		MENU_ITEM(IDM_REFRESH, ID_STR_REFRESHALL), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_SUBMENU(ID_STR_LOGGING, | ||||
| 			MENU_ITEM(IDM_SHOWLOGFILE, ID_STR_SHOWLOGFILE), | ||||
| 			MENU_SEPARATOR(), | ||||
| 			MENU_ITEM(IDM_STARTLOG, ID_STR_STARTLOGGING), | ||||
| 			MENU_ITEM(IDM_STOPLOG, ID_STR_STOPLOGGING), | ||||
| 			MENU_SEPARATOR(), | ||||
| 			MENU_ITEM(IDM_DELETELOGFILE, ID_STR_DELETELOGFILE), | ||||
| 			MENU_ITEM(IDM_DEBUGLOG, ID_STR_DEBUGMODE)), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_ITEM(IDM_QUIT, ID_STR_EXIT) | ||||
| 	}; | ||||
|  | ||||
| 	if (!m_MenuActive && (!meterWindow || !meterWindow->IsClosing())) | ||||
| 	{ | ||||
| 		m_MenuActive = true; | ||||
|  | ||||
| 		// Show context menu, if no actions were executed | ||||
| 		HMENU menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); | ||||
| 		if (menu) | ||||
| 		{ | ||||
| 			SetMenuDefaultItem(menu, IDM_MANAGE, MF_BYCOMMAND); | ||||
|  | ||||
| 			if (_waccess(GetLogger().GetLogFilePath().c_str(), 0) == -1) | ||||
| 			{ | ||||
| 				EnableMenuItem(menu, IDM_SHOWLOGFILE, MF_BYCOMMAND | MF_GRAYED); | ||||
| 				EnableMenuItem(menu, IDM_DELETELOGFILE, MF_BYCOMMAND | MF_GRAYED); | ||||
| 				EnableMenuItem(menu, IDM_STOPLOG, MF_BYCOMMAND | MF_GRAYED); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				EnableMenuItem( | ||||
| 					menu, | ||||
| 					(GetLogger().IsLogToFile()) ? IDM_STARTLOG : IDM_STOPLOG, | ||||
| 					MF_BYCOMMAND | MF_GRAYED); | ||||
| 			} | ||||
|  | ||||
| 			if (m_Debug) | ||||
| 			{ | ||||
| 				CheckMenuItem(menu, IDM_DEBUGLOG, MF_BYCOMMAND | MF_CHECKED); | ||||
| 			} | ||||
|  | ||||
| 			HMENU allSkinsMenu = GetSubMenu(menu, 4); | ||||
| 			if (allSkinsMenu) | ||||
| 			{ | ||||
| 				if (!m_SkinRegistry.IsEmpty()) | ||||
| 				{ | ||||
| 					DeleteMenu(allSkinsMenu, 0, MF_BYPOSITION);  // "No skins available" menuitem | ||||
| 					CreateAllSkinsMenu(allSkinsMenu); | ||||
| 				} | ||||
|  | ||||
| 				if (m_DisableDragging) | ||||
| 				{ | ||||
| 					CheckMenuItem(allSkinsMenu, IDM_DISABLEDRAG, MF_BYCOMMAND | MF_CHECKED); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			HMENU layoutMenu = GetSubMenu(menu, 5); | ||||
| 			if (layoutMenu) | ||||
| 			{ | ||||
| 				if (!m_Layouts.empty()) | ||||
| 				{ | ||||
| 					DeleteMenu(layoutMenu, 0, MF_BYPOSITION);  // "No layouts available" menuitem | ||||
| 					CreateLayoutMenu(layoutMenu); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if (meterWindow) | ||||
| 			{ | ||||
| 				HMENU rainmeterMenu = menu; | ||||
| 				menu = CreateSkinMenu(meterWindow, 0, allSkinsMenu); | ||||
|  | ||||
| 				InsertMenu(menu, IDM_CLOSESKIN, MF_BYCOMMAND | MF_POPUP, (UINT_PTR)rainmeterMenu, L"Rainmeter"); | ||||
| 				InsertMenu(menu, IDM_CLOSESKIN, MF_BYCOMMAND | MF_SEPARATOR, 0, nullptr); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				InsertMenu(menu, 12, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); | ||||
|  | ||||
| 				// Create a menu for all active skins | ||||
| 				int index = 0; | ||||
| 				std::map<std::wstring, MeterWindow*>::const_iterator iter = m_MeterWindows.begin(); | ||||
| 				for (; iter != m_MeterWindows.end(); ++iter) | ||||
| 				{ | ||||
| 					MeterWindow* mw = ((*iter).second); | ||||
| 					HMENU skinMenu = CreateSkinMenu(mw, index, allSkinsMenu); | ||||
| 					InsertMenu(menu, 12, MF_BYPOSITION | MF_POPUP, (UINT_PTR)skinMenu, mw->GetFolderPath().c_str()); | ||||
| 					++index; | ||||
| 				} | ||||
|  | ||||
| 				// Add update notification item | ||||
| 				if (m_NewVersion) | ||||
| 				{ | ||||
| 					InsertMenu(menu, 0, MF_BYPOSITION, IDM_NEW_VERSION, GetString(ID_STR_UPDATEAVAILABLE)); | ||||
| 					HiliteMenuItem(GetTrayWindow()->GetWindow(), menu, 0, MF_BYPOSITION | MF_HILITE); | ||||
| 					InsertMenu(menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			HWND hWnd = WindowFromPoint(pos); | ||||
| 			if (hWnd != nullptr) | ||||
| 			{ | ||||
| 				MeterWindow* mw = GetMeterWindow(hWnd); | ||||
| 				if (mw) | ||||
| 				{ | ||||
| 					// Cancel the mouse event beforehand | ||||
| 					mw->SetMouseLeaveEvent(true); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// Set the window to foreground | ||||
| 			hWnd = meterWindow ? meterWindow->GetWindow() : m_TrayWindow->GetWindow(); | ||||
| 			HWND hWndForeground = GetForegroundWindow(); | ||||
| 			if (hWndForeground != hWnd) | ||||
| 			{ | ||||
| 				DWORD foregroundThreadID = GetWindowThreadProcessId(hWndForeground, nullptr); | ||||
| 				DWORD currentThreadID = GetCurrentThreadId(); | ||||
| 				AttachThreadInput(currentThreadID, foregroundThreadID, TRUE); | ||||
| 				SetForegroundWindow(hWnd); | ||||
| 				AttachThreadInput(currentThreadID, foregroundThreadID, FALSE); | ||||
| 			} | ||||
|  | ||||
| 			// Show context menu | ||||
| 			TrackPopupMenu( | ||||
| 				menu, | ||||
| 				TPM_RIGHTBUTTON | TPM_LEFTALIGN | (*GetString(ID_STR_ISRTL) == L'1' ? TPM_LAYOUTRTL : 0), | ||||
| 				pos.x, | ||||
| 				pos.y, | ||||
| 				0, | ||||
| 				hWnd, | ||||
| 				nullptr); | ||||
|  | ||||
| 			DestroyMenu(menu); | ||||
| 		} | ||||
|  | ||||
| 		m_MenuActive = false; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int Rainmeter::CreateAllSkinsMenuRecursive(HMENU skinMenu, int index) | ||||
| { | ||||
| 	const int initialLevel = m_SkinRegistry.GetFolder(index).level; | ||||
| 	int menuIndex = 0; | ||||
|  | ||||
| 	const size_t max = m_SkinRegistry.GetFolderCount(); | ||||
| 	while (index < max) | ||||
| 	{ | ||||
| 		const SkinRegistry::Folder& skinFolder = m_SkinRegistry.GetFolder(index); | ||||
| 		if (skinFolder.level != initialLevel) | ||||
| 		{ | ||||
| 			return index - 1; | ||||
| 		} | ||||
|  | ||||
| 		HMENU subMenu = CreatePopupMenu(); | ||||
|  | ||||
| 		// Add current folder | ||||
| 		InsertMenu(skinMenu, menuIndex, MF_POPUP | MF_BYPOSITION, (UINT_PTR)subMenu, skinFolder.name.c_str()); | ||||
|  | ||||
| 		// Add subfolders | ||||
| 		const bool hasSubfolder = (index + 1) < max && m_SkinRegistry.GetFolder(index + 1).level == initialLevel + 1; | ||||
| 		if (hasSubfolder) | ||||
| 		{ | ||||
| 			index = CreateAllSkinsMenuRecursive(subMenu, index + 1); | ||||
| 		} | ||||
|  | ||||
| 		// Add files | ||||
| 		{ | ||||
| 			int fileIndex = 0; | ||||
| 			int fileCount = (int)skinFolder.files.size(); | ||||
| 			for ( ; fileIndex < fileCount; ++fileIndex) | ||||
| 			{ | ||||
| 				InsertMenu(subMenu, fileIndex, MF_STRING | MF_BYPOSITION, skinFolder.baseID + fileIndex, skinFolder.files[fileIndex].c_str()); | ||||
| 			} | ||||
|  | ||||
| 			if (skinFolder.active) | ||||
| 			{ | ||||
| 				UINT checkPos = skinFolder.active - 1; | ||||
| 				CheckMenuRadioItem(subMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); | ||||
| 			} | ||||
|  | ||||
| 			if (hasSubfolder && fileIndex != 0) | ||||
| 			{ | ||||
| 				InsertMenu(subMenu, fileIndex, MF_SEPARATOR | MF_BYPOSITION, 0, nullptr); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		++menuIndex; | ||||
| 		++index; | ||||
| 	} | ||||
|  | ||||
| 	return index; | ||||
| } | ||||
|  | ||||
| HMENU Rainmeter::CreateSkinMenu(MeterWindow* meterWindow, int index, HMENU menu) | ||||
| { | ||||
| 	static const MenuTemplate s_Menu[] = | ||||
| 	{ | ||||
| 		MENU_ITEM(IDM_SKIN_OPENSKINSFOLDER, 0), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_SUBMENU(ID_STR_VARIANTS, | ||||
| 			MENU_SEPARATOR()), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_SUBMENU(ID_STR_SETTINGS, | ||||
| 			MENU_SUBMENU(ID_STR_POSITION, | ||||
| 				MENU_SUBMENU(ID_STR_DISPLAYMONITOR, | ||||
| 					MENU_ITEM(IDM_SKIN_MONITOR_PRIMARY, ID_STR_USEDEFAULTMONITOR), | ||||
| 					MENU_ITEM(ID_MONITOR_FIRST, ID_STR_VIRTUALSCREEN), | ||||
| 					MENU_SEPARATOR(), | ||||
| 					MENU_SEPARATOR(), | ||||
| 					MENU_ITEM(IDM_SKIN_MONITOR_AUTOSELECT, ID_STR_AUTOSELECTMONITOR)), | ||||
| 				MENU_SEPARATOR(), | ||||
| 				MENU_ITEM(IDM_SKIN_VERYTOPMOST, ID_STR_STAYTOPMOST), | ||||
| 				MENU_ITEM(IDM_SKIN_TOPMOST, ID_STR_TOPMOST), | ||||
| 				MENU_ITEM(IDM_SKIN_NORMAL, ID_STR_NORMAL), | ||||
| 				MENU_ITEM(IDM_SKIN_BOTTOM, ID_STR_BOTTOM), | ||||
| 				MENU_ITEM(IDM_SKIN_ONDESKTOP, ID_STR_ONDESKTOP), | ||||
| 				MENU_SEPARATOR(), | ||||
| 				MENU_ITEM(IDM_SKIN_FROMRIGHT, ID_STR_FROMRIGHT), | ||||
| 				MENU_ITEM(IDM_SKIN_FROMBOTTOM, ID_STR_FROMBOTTOM), | ||||
| 				MENU_ITEM(IDM_SKIN_XPERCENTAGE, ID_STR_XASPERCENTAGE), | ||||
| 				MENU_ITEM(IDM_SKIN_YPERCENTAGE, ID_STR_YASPERCENTAGE)), | ||||
| 			MENU_SUBMENU(ID_STR_TRANSPARENCY, | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_0, ID_STR_0PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_10, ID_STR_10PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_20, ID_STR_20PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_30, ID_STR_30PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_40, ID_STR_40PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_50, ID_STR_50PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_60, ID_STR_60PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_70, ID_STR_70PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_80, ID_STR_80PERCENT), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_90, ID_STR_90PERCENT), | ||||
| 				MENU_SEPARATOR(), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_FADEIN, ID_STR_FADEIN), | ||||
| 				MENU_ITEM(IDM_SKIN_TRANSPARENCY_FADEOUT, ID_STR_FADEOUT)), | ||||
| 			MENU_SEPARATOR(), | ||||
| 			MENU_ITEM(IDM_SKIN_HIDEONMOUSE, ID_STR_HIDEONMOUSEOVER), | ||||
| 			MENU_ITEM(IDM_SKIN_DRAGGABLE, ID_STR_DRAGGABLE), | ||||
| 			MENU_ITEM(IDM_SKIN_REMEMBERPOSITION, ID_STR_SAVEPOSITION), | ||||
| 			MENU_ITEM(IDM_SKIN_SNAPTOEDGES, ID_STR_SNAPTOEDGES), | ||||
| 			MENU_ITEM(IDM_SKIN_CLICKTHROUGH, ID_STR_CLICKTHROUGH), | ||||
| 			MENU_ITEM(IDM_SKIN_KEEPONSCREEN, ID_STR_KEEPONSCREEN)), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_ITEM(IDM_SKIN_MANAGESKIN, ID_STR_MANAGESKIN), | ||||
| 		MENU_ITEM(IDM_SKIN_EDITSKIN, ID_STR_EDITSKIN), | ||||
| 		MENU_ITEM(IDM_SKIN_REFRESH, ID_STR_REFRESHSKIN), | ||||
| 		MENU_SEPARATOR(), | ||||
| 		MENU_ITEM(IDM_CLOSESKIN, ID_STR_UNLOADSKIN) | ||||
| 	}; | ||||
|  | ||||
| 	HMENU skinMenu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); | ||||
| 	if (skinMenu) | ||||
| 	{ | ||||
| 		// Tick the position | ||||
| 		HMENU settingsMenu = GetSubMenu(skinMenu, 4); | ||||
| 		if (settingsMenu) | ||||
| 		{ | ||||
| 			HMENU posMenu = GetSubMenu(settingsMenu, 0); | ||||
| 			if (posMenu) | ||||
| 			{ | ||||
| 				UINT checkPos = IDM_SKIN_NORMAL - (UINT)meterWindow->GetWindowZPosition(); | ||||
| 				CheckMenuRadioItem(posMenu, checkPos, checkPos, checkPos, MF_BYCOMMAND); | ||||
|  | ||||
| 				if (meterWindow->GetXFromRight()) CheckMenuItem(posMenu, IDM_SKIN_FROMRIGHT, MF_BYCOMMAND | MF_CHECKED); | ||||
| 				if (meterWindow->GetYFromBottom()) CheckMenuItem(posMenu, IDM_SKIN_FROMBOTTOM, MF_BYCOMMAND | MF_CHECKED); | ||||
| 				if (meterWindow->GetXPercentage()) CheckMenuItem(posMenu, IDM_SKIN_XPERCENTAGE, MF_BYCOMMAND | MF_CHECKED); | ||||
| 				if (meterWindow->GetYPercentage()) CheckMenuItem(posMenu, IDM_SKIN_YPERCENTAGE, MF_BYCOMMAND | MF_CHECKED); | ||||
|  | ||||
| 				HMENU monitorMenu = GetSubMenu(posMenu, 0); | ||||
| 				if (monitorMenu) | ||||
| 				{ | ||||
| 					CreateMonitorMenu(monitorMenu, meterWindow); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// Tick the transparency | ||||
| 			HMENU alphaMenu = GetSubMenu(settingsMenu, 1); | ||||
| 			if (alphaMenu) | ||||
| 			{ | ||||
| 				UINT checkPos = (UINT)(10 - meterWindow->GetAlphaValue() / 25.5); | ||||
| 				checkPos = min(9, checkPos); | ||||
| 				checkPos = max(0, checkPos); | ||||
| 				CheckMenuRadioItem(alphaMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); | ||||
|  | ||||
| 				switch (meterWindow->GetWindowHide()) | ||||
| 				{ | ||||
| 				case HIDEMODE_FADEIN: | ||||
| 					CheckMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_CHECKED); | ||||
| 					EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_GRAYED); | ||||
| 					break; | ||||
|  | ||||
| 				case HIDEMODE_FADEOUT: | ||||
| 					CheckMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_CHECKED); | ||||
| 					EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_GRAYED); | ||||
| 					break; | ||||
|  | ||||
| 				case HIDEMODE_HIDE: | ||||
| 					EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_GRAYED); | ||||
| 					EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_GRAYED); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// Tick the settings | ||||
| 			switch (meterWindow->GetWindowHide()) | ||||
| 			{ | ||||
| 			case HIDEMODE_HIDE: | ||||
| 				CheckMenuItem(settingsMenu, IDM_SKIN_HIDEONMOUSE, MF_BYCOMMAND | MF_CHECKED); | ||||
| 				break; | ||||
|  | ||||
| 			case HIDEMODE_FADEIN: | ||||
| 			case HIDEMODE_FADEOUT: | ||||
| 				EnableMenuItem(settingsMenu, IDM_SKIN_HIDEONMOUSE, MF_BYCOMMAND | MF_GRAYED); | ||||
| 				break; | ||||
| 			} | ||||
|  | ||||
| 			if (meterWindow->GetSnapEdges()) | ||||
| 			{ | ||||
| 				CheckMenuItem(settingsMenu, IDM_SKIN_SNAPTOEDGES, MF_BYCOMMAND | MF_CHECKED); | ||||
| 			} | ||||
|  | ||||
| 			if (meterWindow->GetSavePosition()) | ||||
| 			{ | ||||
| 				CheckMenuItem(settingsMenu, IDM_SKIN_REMEMBERPOSITION, MF_BYCOMMAND | MF_CHECKED); | ||||
| 			} | ||||
|  | ||||
| 			if (m_DisableDragging) | ||||
| 			{ | ||||
| 				EnableMenuItem(settingsMenu, IDM_SKIN_DRAGGABLE, MF_BYCOMMAND | MF_GRAYED); | ||||
| 			} | ||||
| 			else if (meterWindow->GetWindowDraggable()) | ||||
| 			{ | ||||
| 				CheckMenuItem(settingsMenu, IDM_SKIN_DRAGGABLE, MF_BYCOMMAND | MF_CHECKED); | ||||
| 			} | ||||
|  | ||||
| 			if (meterWindow->GetClickThrough()) | ||||
| 			{ | ||||
| 				CheckMenuItem(settingsMenu, IDM_SKIN_CLICKTHROUGH, MF_BYCOMMAND | MF_CHECKED); | ||||
| 			} | ||||
|  | ||||
| 			if (meterWindow->GetKeepOnScreen()) | ||||
| 			{ | ||||
| 				CheckMenuItem(settingsMenu, IDM_SKIN_KEEPONSCREEN, MF_BYCOMMAND | MF_CHECKED); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// Add the name of the Skin to the menu | ||||
| 		const std::wstring& skinName = meterWindow->GetFolderPath(); | ||||
| 		ModifyMenu(skinMenu, IDM_SKIN_OPENSKINSFOLDER, MF_BYCOMMAND, IDM_SKIN_OPENSKINSFOLDER, skinName.c_str()); | ||||
| 		SetMenuDefaultItem(skinMenu, IDM_SKIN_OPENSKINSFOLDER, FALSE); | ||||
|  | ||||
| 		// Remove dummy menuitem from the variants menu | ||||
| 		HMENU variantsMenu = GetSubMenu(skinMenu, 2); | ||||
| 		if (variantsMenu) | ||||
| 		{ | ||||
| 			DeleteMenu(variantsMenu, 0, MF_BYPOSITION); | ||||
| 		} | ||||
|  | ||||
| 		// Give the menuitem the unique id that depends on the skin | ||||
| 		ChangeSkinIndex(skinMenu, index); | ||||
|  | ||||
| 		// Add the variants menu | ||||
| 		if (variantsMenu) | ||||
| 		{ | ||||
| 			const SkinRegistry::Folder& skinFolder = *m_SkinRegistry.FindFolder(skinName); | ||||
| 			for (int i = 0, isize = (int)skinFolder.files.size(); i < isize; ++i) | ||||
| 			{ | ||||
| 				InsertMenu(variantsMenu, i, MF_BYPOSITION, skinFolder.baseID + i, skinFolder.files[i].c_str()); | ||||
| 			} | ||||
|  | ||||
| 			if (skinFolder.active) | ||||
| 			{ | ||||
| 				UINT checkPos = skinFolder.active - 1; | ||||
| 				CheckMenuRadioItem(variantsMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// Add skin root menu | ||||
| 		int itemCount = GetMenuItemCount(menu); | ||||
| 		if (itemCount > 0) | ||||
| 		{ | ||||
| 			std::wstring root = meterWindow->GetFolderPath(); | ||||
| 			std::wstring::size_type pos = root.find_first_of(L'\\'); | ||||
| 			if (pos != std::wstring::npos) | ||||
| 			{ | ||||
| 				root.erase(pos); | ||||
| 			} | ||||
|  | ||||
| 			for (int i = 0; i < itemCount; ++i) | ||||
| 			{ | ||||
| 				UINT state = GetMenuState(menu, i, MF_BYPOSITION); | ||||
| 				if (state == 0xFFFFFFFF || (state & MF_POPUP) == 0) break; | ||||
|  | ||||
| 				WCHAR buffer[MAX_PATH]; | ||||
| 				if (GetMenuString(menu, i, buffer, MAX_PATH, MF_BYPOSITION)) | ||||
| 				{ | ||||
| 					if (_wcsicmp(root.c_str(), buffer) == 0) | ||||
| 					{ | ||||
| 						HMENU skinRootMenu = GetSubMenu(menu, i); | ||||
| 						if (skinRootMenu) | ||||
| 						{ | ||||
| 							InsertMenu(skinMenu, 3, MF_BYPOSITION | MF_POPUP, (UINT_PTR)skinRootMenu, root.c_str()); | ||||
| 						} | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// Add custom actions to the context menu | ||||
| 		std::wstring contextTitle = meterWindow->GetParser().ReadString(L"Rainmeter", L"ContextTitle", L""); | ||||
| 		if (!contextTitle.empty()) | ||||
| 		{ | ||||
| 			auto isTitleSeparator = [](const std::wstring& title) | ||||
| 			{ | ||||
| 				return title.find_first_not_of(L'-') == std::wstring::npos; | ||||
| 			}; | ||||
|  | ||||
| 			std::wstring contextAction = meterWindow->GetParser().ReadString(L"Rainmeter", L"ContextAction", L""); | ||||
| 			if (!contextAction.empty() || isTitleSeparator(contextTitle)) | ||||
| 			{ | ||||
| 				std::vector<std::wstring> cTitles; | ||||
| 				WCHAR buffer[128]; | ||||
| 				int i = 1; | ||||
|  | ||||
| 				while (!contextTitle.empty() && | ||||
| 					  (!contextAction.empty() || isTitleSeparator(contextTitle)) && | ||||
| 					  (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 three items | ||||
| 				size_t titleSize = cTitles.size(); | ||||
| 				if (titleSize <= 3) | ||||
| 				{ | ||||
| 					size_t position = 0; | ||||
| 					for (size_t i = 0; i < titleSize; ++i) | ||||
| 					{ | ||||
| 						if (isTitleSeparator(cTitles[i])) | ||||
| 						{ | ||||
| 							// Separators not allowed in main top-level menu | ||||
| 							--position; | ||||
| 						} | ||||
| 						else | ||||
| 						{ | ||||
| 							InsertMenu(skinMenu, position + 1, MF_BYPOSITION | MF_STRING, (index << 16) | (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i), cTitles[i].c_str()); | ||||
| 						} | ||||
|  | ||||
| 						++position; | ||||
| 					} | ||||
|  | ||||
| 					if (position != 0) | ||||
| 					{ | ||||
| 						InsertMenu(skinMenu, 1, MF_BYPOSITION | MF_STRING | MF_GRAYED, 0, L"Custom skin actions"); | ||||
| 						InsertMenu(skinMenu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); | ||||
| 					} | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					HMENU customMenu = CreatePopupMenu(); | ||||
| 					InsertMenu(skinMenu, 1, MF_BYPOSITION | MF_POPUP, (UINT_PTR)customMenu, L"Custom skin actions"); | ||||
| 				 | ||||
| 					for (size_t i = 0; i < titleSize; ++i) | ||||
| 					{ | ||||
| 						if (isTitleSeparator(cTitles[i])) | ||||
| 						{ | ||||
| 							AppendMenu(customMenu, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); | ||||
| 						} | ||||
| 						else | ||||
| 						{ | ||||
| 							AppendMenu(customMenu, MF_BYPOSITION | MF_STRING, (index << 16) | (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i), cTitles[i].c_str()); | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 					InsertMenu(skinMenu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return skinMenu; | ||||
| } | ||||
|  | ||||
| void Rainmeter::CreateLayoutMenu(HMENU layoutMenu) | ||||
| { | ||||
| 	for (size_t i = 0, isize = m_Layouts.size(); i < isize; ++i) | ||||
| 	{ | ||||
| 		InsertMenu(layoutMenu, i, MF_BYPOSITION, ID_THEME_FIRST + i, m_Layouts[i].c_str()); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void Rainmeter::CreateMonitorMenu(HMENU monitorMenu, MeterWindow* meterWindow) | ||||
| { | ||||
| 	bool screenDefined = meterWindow->GetXScreenDefined(); | ||||
| 	int screenIndex = meterWindow->GetXScreen(); | ||||
|  | ||||
| 	// for the "Specified monitor" (@n) | ||||
| 	const size_t numOfMonitors = System::GetMonitorCount();  // intentional | ||||
| 	const std::vector<MonitorInfo>& monitors = System::GetMultiMonitorInfo().monitors; | ||||
|  | ||||
| 	int i = 1; | ||||
| 	for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter, ++i) | ||||
| 	{ | ||||
| 		WCHAR buffer[64]; | ||||
| 		size_t len = _snwprintf_s(buffer, _TRUNCATE, L"@%i: ", i); | ||||
|  | ||||
| 		std::wstring item(buffer, len); | ||||
|  | ||||
| 		if ((*iter).monitorName.size() > 32) | ||||
| 		{ | ||||
| 			item.append((*iter).monitorName, 0, 32); | ||||
| 			item += L"..."; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			item += (*iter).monitorName; | ||||
| 		} | ||||
|  | ||||
| 		InsertMenu(monitorMenu, | ||||
| 			i + 2, | ||||
| 			MF_BYPOSITION | ((screenDefined && screenIndex == i) ? MF_CHECKED : MF_UNCHECKED) | ((!(*iter).active) ? MF_GRAYED : MF_ENABLED), | ||||
| 			ID_MONITOR_FIRST + i, | ||||
| 			item.c_str()); | ||||
| 	} | ||||
|  | ||||
| 	if (!screenDefined) | ||||
| 	{ | ||||
| 		CheckMenuItem(monitorMenu, IDM_SKIN_MONITOR_PRIMARY, MF_BYCOMMAND | MF_CHECKED); | ||||
| 	} | ||||
|  | ||||
| 	if (screenDefined && screenIndex == 0) | ||||
| 	{ | ||||
| 		CheckMenuItem(monitorMenu, ID_MONITOR_FIRST, MF_BYCOMMAND | MF_CHECKED); | ||||
| 	} | ||||
|  | ||||
| 	if (meterWindow->GetAutoSelectScreen()) | ||||
| 	{ | ||||
| 		CheckMenuItem(monitorMenu, IDM_SKIN_MONITOR_AUTOSELECT, MF_BYCOMMAND | MF_CHECKED); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void Rainmeter::ChangeSkinIndex(HMENU menu, int index) | ||||
| { | ||||
| 	if (index > 0) | ||||
| 	{ | ||||
| 		int count = GetMenuItemCount(menu); | ||||
|  | ||||
| 		for (int i = 0; i < count; ++i) | ||||
| 		{ | ||||
| 			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); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void Rainmeter::ShowLogFile() | ||||
| { | ||||
| 	std::wstring logFile = L'"' + GetLogger().GetLogFilePath(); | ||||
|   | ||||
| @@ -25,6 +25,7 @@ | ||||
| #include <list> | ||||
| #include <string> | ||||
| #include "CommandHandler.h" | ||||
| #include "ContextMenu.h" | ||||
| #include "Logger.h" | ||||
| #include "MeterWindow.h" | ||||
| #include "SkinRegistry.h" | ||||
| @@ -162,8 +163,8 @@ public: | ||||
|  | ||||
| 	int ShowMessage(HWND parent, const WCHAR* text, UINT type); | ||||
|  | ||||
| 	bool IsMenuActive() { return m_MenuActive; } | ||||
| 	void ShowContextMenu(POINT pos, MeterWindow* meterWindow); | ||||
| 	bool IsMenuActive() { return m_ContextMenu.IsMenuActive(); } | ||||
| 	void ShowContextMenu(POINT pos, MeterWindow* mw) { return m_ContextMenu.ShowMenu(pos, mw); } | ||||
|  | ||||
| 	const std::wstring& GetTrayExecuteR() { return m_TrayExecuteR; } | ||||
| 	const std::wstring& GetTrayExecuteM() { return m_TrayExecuteM; } | ||||
| @@ -180,6 +181,7 @@ public: | ||||
| 	void PreserveSetting(const std::wstring& from, LPCTSTR key, bool replace = true); | ||||
|  | ||||
| 	friend class CommandHandler; | ||||
| 	friend class ContextMenu; | ||||
| 	friend class DialogManage; | ||||
|  | ||||
| private: | ||||
| @@ -199,14 +201,7 @@ private: | ||||
| 	void SetLoadOrder(int folderIndex, int order); | ||||
| 	int GetLoadOrder(const std::wstring& folderPath); | ||||
| 	void UpdateDesktopWorkArea(bool reset); | ||||
| 	HMENU CreateSkinMenu(MeterWindow* meterWindow, int index, HMENU menu); | ||||
| 	void ChangeSkinIndex(HMENU subMenu, int index); | ||||
|  | ||||
| 	void CreateAllSkinsMenu(HMENU skinMenu) { CreateAllSkinsMenuRecursive(skinMenu, 0); } | ||||
| 	int CreateAllSkinsMenuRecursive(HMENU skinMenu, int index); | ||||
|  | ||||
| 	void CreateLayoutMenu(HMENU layoutMenu); | ||||
| 	void CreateMonitorMenu(HMENU monitorMenu, MeterWindow* meterWindow); | ||||
| 	void CreateOptionsFile(); | ||||
| 	void CreateDataFile(); | ||||
| 	void CreateComponentFolders(bool defaultIniLocation); | ||||
| @@ -249,8 +244,6 @@ private: | ||||
|  | ||||
| 	bool m_NormalStayDesktop; | ||||
|  | ||||
| 	bool m_MenuActive; | ||||
|  | ||||
| 	bool m_DisableRDP; | ||||
|  | ||||
| 	bool m_DisableDragging; | ||||
| @@ -258,7 +251,7 @@ private: | ||||
| 	std::wstring m_SkinEditor; | ||||
|  | ||||
| 	CommandHandler m_CommandHandler; | ||||
|  | ||||
| 	ContextMenu m_ContextMenu; | ||||
| 	SkinRegistry m_SkinRegistry; | ||||
|  | ||||
| 	ConfigParser* m_CurrentParser; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Birunthan Mohanathas
					Birunthan Mohanathas