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); | 			HMENU menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); | ||||||
| 			if (menu) | 			if (menu) | ||||||
| 			{ | 			{ | ||||||
| 				GetRainmeter().CreateMonitorMenu(menu, m_SkinWindow); | 				ContextMenu::CreateMonitorMenu(menu, m_SkinWindow); | ||||||
|  |  | ||||||
| 				RECT r; | 				RECT r; | ||||||
| 				GetWindowRect((HWND)lParam, &r); | 				GetWindowRect((HWND)lParam, &r); | ||||||
|   | |||||||
| @@ -90,6 +90,9 @@ | |||||||
|     <ClCompile Include="ConfigParser_Test.cpp"> |     <ClCompile Include="ConfigParser_Test.cpp"> | ||||||
|       <ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild> |       <ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |     <ClCompile Include="ContextMenu.cpp"> | ||||||
|  |       <PrecompiledHeader>Use</PrecompiledHeader> | ||||||
|  |     </ClCompile> | ||||||
|     <ClCompile Include="DialogAbout.cpp"> |     <ClCompile Include="DialogAbout.cpp"> | ||||||
|       <PrecompiledHeader>Use</PrecompiledHeader> |       <PrecompiledHeader>Use</PrecompiledHeader> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
| @@ -315,6 +318,7 @@ | |||||||
|     <ClInclude Include="..\Common\Gfx\Util\WICBitmapLockGDIP.h" /> |     <ClInclude Include="..\Common\Gfx\Util\WICBitmapLockGDIP.h" /> | ||||||
|     <ClInclude Include="CommandHandler.h" /> |     <ClInclude Include="CommandHandler.h" /> | ||||||
|     <ClInclude Include="ConfigParser.h" /> |     <ClInclude Include="ConfigParser.h" /> | ||||||
|  |     <ClInclude Include="ContextMenu.h" /> | ||||||
|     <ClInclude Include="DialogAbout.h" /> |     <ClInclude Include="DialogAbout.h" /> | ||||||
|     <ClInclude Include="Error.h" /> |     <ClInclude Include="Error.h" /> | ||||||
|     <ClInclude Include="Group.h" /> |     <ClInclude Include="Group.h" /> | ||||||
|   | |||||||
| @@ -387,6 +387,9 @@ | |||||||
|     <ClCompile Include="SkinRegistry_Test.cpp"> |     <ClCompile Include="SkinRegistry_Test.cpp"> | ||||||
|       <Filter>Source Files</Filter> |       <Filter>Source Files</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |     <ClCompile Include="ContextMenu.cpp"> | ||||||
|  |       <Filter>Source Files</Filter> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClInclude Include="ConfigParser.h"> |     <ClInclude Include="ConfigParser.h"> | ||||||
| @@ -662,6 +665,9 @@ | |||||||
|     <ClInclude Include="SkinRegistry.h"> |     <ClInclude Include="SkinRegistry.h"> | ||||||
|       <Filter>Header Files</Filter> |       <Filter>Header Files</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  |     <ClInclude Include="ContextMenu.h"> | ||||||
|  |       <Filter>Header Files</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ResourceCompile Include="Library.rc"> |     <ResourceCompile Include="Library.rc"> | ||||||
|   | |||||||
| @@ -17,7 +17,6 @@ | |||||||
| */ | */ | ||||||
|  |  | ||||||
| #include "StdAfx.h" | #include "StdAfx.h" | ||||||
| #include "../Common/MenuTemplate.h" |  | ||||||
| #include "../Common/PathUtil.h" | #include "../Common/PathUtil.h" | ||||||
| #include "Rainmeter.h" | #include "Rainmeter.h" | ||||||
| #include "TrayWindow.h" | #include "TrayWindow.h" | ||||||
| @@ -28,7 +27,6 @@ | |||||||
| #include "MeasureNet.h" | #include "MeasureNet.h" | ||||||
| #include "MeasureCPU.h" | #include "MeasureCPU.h" | ||||||
| #include "MeterString.h" | #include "MeterString.h" | ||||||
| #include "resource.h" |  | ||||||
| #include "UpdateCheck.h" | #include "UpdateCheck.h" | ||||||
| #include "../Version.h" | #include "../Version.h" | ||||||
|  |  | ||||||
| @@ -115,7 +113,6 @@ Rainmeter::Rainmeter() : | |||||||
| 	m_DesktopWorkAreaChanged(false), | 	m_DesktopWorkAreaChanged(false), | ||||||
| 	m_DesktopWorkAreaType(false), | 	m_DesktopWorkAreaType(false), | ||||||
| 	m_NormalStayDesktop(true), | 	m_NormalStayDesktop(true), | ||||||
| 	m_MenuActive(false), |  | ||||||
| 	m_DisableRDP(false), | 	m_DisableRDP(false), | ||||||
| 	m_DisableDragging(false), | 	m_DisableDragging(false), | ||||||
| 	m_CurrentParser(), | 	m_CurrentParser(), | ||||||
| @@ -1708,610 +1705,6 @@ int Rainmeter::ShowMessage(HWND parent, const WCHAR* text, UINT type) | |||||||
| 	return MessageBox(parent, text, APPNAME, 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() | void Rainmeter::ShowLogFile() | ||||||
| { | { | ||||||
| 	std::wstring logFile = L'"' + GetLogger().GetLogFilePath(); | 	std::wstring logFile = L'"' + GetLogger().GetLogFilePath(); | ||||||
|   | |||||||
| @@ -25,6 +25,7 @@ | |||||||
| #include <list> | #include <list> | ||||||
| #include <string> | #include <string> | ||||||
| #include "CommandHandler.h" | #include "CommandHandler.h" | ||||||
|  | #include "ContextMenu.h" | ||||||
| #include "Logger.h" | #include "Logger.h" | ||||||
| #include "MeterWindow.h" | #include "MeterWindow.h" | ||||||
| #include "SkinRegistry.h" | #include "SkinRegistry.h" | ||||||
| @@ -162,8 +163,8 @@ public: | |||||||
|  |  | ||||||
| 	int ShowMessage(HWND parent, const WCHAR* text, UINT type); | 	int ShowMessage(HWND parent, const WCHAR* text, UINT type); | ||||||
|  |  | ||||||
| 	bool IsMenuActive() { return m_MenuActive; } | 	bool IsMenuActive() { return m_ContextMenu.IsMenuActive(); } | ||||||
| 	void ShowContextMenu(POINT pos, MeterWindow* meterWindow); | 	void ShowContextMenu(POINT pos, MeterWindow* mw) { return m_ContextMenu.ShowMenu(pos, mw); } | ||||||
|  |  | ||||||
| 	const std::wstring& GetTrayExecuteR() { return m_TrayExecuteR; } | 	const std::wstring& GetTrayExecuteR() { return m_TrayExecuteR; } | ||||||
| 	const std::wstring& GetTrayExecuteM() { return m_TrayExecuteM; } | 	const std::wstring& GetTrayExecuteM() { return m_TrayExecuteM; } | ||||||
| @@ -180,6 +181,7 @@ public: | |||||||
| 	void PreserveSetting(const std::wstring& from, LPCTSTR key, bool replace = true); | 	void PreserveSetting(const std::wstring& from, LPCTSTR key, bool replace = true); | ||||||
|  |  | ||||||
| 	friend class CommandHandler; | 	friend class CommandHandler; | ||||||
|  | 	friend class ContextMenu; | ||||||
| 	friend class DialogManage; | 	friend class DialogManage; | ||||||
|  |  | ||||||
| private: | private: | ||||||
| @@ -199,14 +201,7 @@ private: | |||||||
| 	void SetLoadOrder(int folderIndex, int order); | 	void SetLoadOrder(int folderIndex, int order); | ||||||
| 	int GetLoadOrder(const std::wstring& folderPath); | 	int GetLoadOrder(const std::wstring& folderPath); | ||||||
| 	void UpdateDesktopWorkArea(bool reset); | 	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 CreateOptionsFile(); | ||||||
| 	void CreateDataFile(); | 	void CreateDataFile(); | ||||||
| 	void CreateComponentFolders(bool defaultIniLocation); | 	void CreateComponentFolders(bool defaultIniLocation); | ||||||
| @@ -249,8 +244,6 @@ private: | |||||||
|  |  | ||||||
| 	bool m_NormalStayDesktop; | 	bool m_NormalStayDesktop; | ||||||
|  |  | ||||||
| 	bool m_MenuActive; |  | ||||||
|  |  | ||||||
| 	bool m_DisableRDP; | 	bool m_DisableRDP; | ||||||
|  |  | ||||||
| 	bool m_DisableDragging; | 	bool m_DisableDragging; | ||||||
| @@ -258,7 +251,7 @@ private: | |||||||
| 	std::wstring m_SkinEditor; | 	std::wstring m_SkinEditor; | ||||||
|  |  | ||||||
| 	CommandHandler m_CommandHandler; | 	CommandHandler m_CommandHandler; | ||||||
|  | 	ContextMenu m_ContextMenu; | ||||||
| 	SkinRegistry m_SkinRegistry; | 	SkinRegistry m_SkinRegistry; | ||||||
|  |  | ||||||
| 	ConfigParser* m_CurrentParser; | 	ConfigParser* m_CurrentParser; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Birunthan Mohanathas
					Birunthan Mohanathas