mirror of
				https://github.com/chibicitiberiu/rainmeter-studio.git
				synced 2024-02-24 04:33:31 +00:00 
			
		
		
		
	- Added the workaround to pin the window to desktop in Vista/7 with Aero.
- Added !RainmeterSetTransparency, !RainmeterShowFade, !RainmeterHideFade, !RainmeterToggleFade. - Added the function to log the installed font families to the log file when Debug=1 is set. - Added the workaround for issue 145. The wrong drawing position was fixed when AntiAlias=0 is set.
This commit is contained in:
		| @@ -20,6 +20,7 @@ | |||||||
| #include "ConfigParser.h" | #include "ConfigParser.h" | ||||||
| #include "Litestep.h" | #include "Litestep.h" | ||||||
| #include "Rainmeter.h" | #include "Rainmeter.h" | ||||||
|  | #include "System.h" | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
|  |  | ||||||
| extern CRainmeter* Rainmeter; | extern CRainmeter* Rainmeter; | ||||||
| @@ -219,9 +220,9 @@ void CConfigParser::SetMultiMonitorVariables(bool reset) | |||||||
| 		SetMonitorVariable(L"VSCREENAREAHEIGHT", buffer); | 		SetMonitorVariable(L"VSCREENAREAHEIGHT", buffer); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (CMeterWindow::GetMonitorCount() > 0) | 	if (CSystem::GetMonitorCount() > 0) | ||||||
| 	{ | 	{ | ||||||
| 		const MULTIMONITOR_INFO& multimonInfo = CMeterWindow::GetMultiMonitorInfo(); | 		const MULTIMONITOR_INFO& multimonInfo = CSystem::GetMultiMonitorInfo(); | ||||||
| 		const std::vector<MONITOR_INFO>& monitors = multimonInfo.monitors; | 		const std::vector<MONITOR_INFO>& monitors = multimonInfo.monitors; | ||||||
|  |  | ||||||
| 		for (size_t i = 0; i < monitors.size(); i++) | 		for (size_t i = 0; i < monitors.size(); i++) | ||||||
| @@ -290,12 +291,12 @@ void CConfigParser::SetAutoSelectedMonitorVariables(CMeterWindow* meterWindow) | |||||||
|  |  | ||||||
| 	if (meterWindow) | 	if (meterWindow) | ||||||
| 	{ | 	{ | ||||||
| 		if (CMeterWindow::GetMonitorCount() > 0) | 		if (CSystem::GetMonitorCount() > 0) | ||||||
| 		{ | 		{ | ||||||
| 			TCHAR buffer[256]; | 			TCHAR buffer[256]; | ||||||
| 			int w1, w2, s1, s2; | 			int w1, w2, s1, s2; | ||||||
|  |  | ||||||
| 			const MULTIMONITOR_INFO& multimonInfo = CMeterWindow::GetMultiMonitorInfo(); | 			const MULTIMONITOR_INFO& multimonInfo = CSystem::GetMultiMonitorInfo(); | ||||||
| 			const std::vector<MONITOR_INFO>& monitors = multimonInfo.monitors; | 			const std::vector<MONITOR_INFO>& monitors = multimonInfo.monitors; | ||||||
|  |  | ||||||
| 			if (meterWindow->GetXScreenDefined()) | 			if (meterWindow->GetXScreenDefined()) | ||||||
|   | |||||||
| @@ -54,11 +54,12 @@ public: | |||||||
| 	std::wstring& GetFilename() { return m_Filename; } | 	std::wstring& GetFilename() { return m_Filename; } | ||||||
| 	const std::vector<std::wstring>& GetSections(); | 	const std::vector<std::wstring>& GetSections(); | ||||||
|  |  | ||||||
|  |  | ||||||
| 	// Returns an int if the formula was read successfully, -1 for failure. | 	// Returns an int if the formula was read successfully, -1 for failure. | ||||||
| 	int ReadFormula(std::wstring& result, double* number); | 	int ReadFormula(std::wstring& result, double* number); | ||||||
|  |  | ||||||
| 	static std::vector<std::wstring> Tokenize(const std::wstring& str, const std::wstring delimiters); | 	static std::vector<std::wstring> Tokenize(const std::wstring& str, const std::wstring delimiters); | ||||||
|  | 	static double ParseDouble(const std::wstring& string, double defValue, bool rejectExp = false); | ||||||
|  | 	static Gdiplus::Color ParseColor(LPCTSTR string); | ||||||
|  |  | ||||||
| 	static void ClearMultiMonitorVariables() { c_MonitorVariables.clear(); } | 	static void ClearMultiMonitorVariables() { c_MonitorVariables.clear(); } | ||||||
| 	static void UpdateWorkareaVariables() { SetMultiMonitorVariables(false); } | 	static void UpdateWorkareaVariables() { SetMultiMonitorVariables(false); } | ||||||
| @@ -68,9 +69,6 @@ private: | |||||||
| 	void ReadVariables(); | 	void ReadVariables(); | ||||||
| 	void ReplaceVariables(std::wstring& result); | 	void ReplaceVariables(std::wstring& result); | ||||||
|  |  | ||||||
| 	double ParseDouble(const std::wstring& string, double defValue, bool rejectExp = false); |  | ||||||
| 	Gdiplus::Color ParseColor(LPCTSTR string); |  | ||||||
|  |  | ||||||
| 	void ReadIniFile(const std::wstring& strFileName, int depth = 0); | 	void ReadIniFile(const std::wstring& strFileName, int depth = 0); | ||||||
| 	void SetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strValue); | 	void SetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strValue); | ||||||
| 	const std::wstring& GetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strDefault); | 	const std::wstring& GetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strDefault); | ||||||
|   | |||||||
| @@ -2610,6 +2610,10 @@ | |||||||
| 					/> | 					/> | ||||||
| 				</FileConfiguration> | 				</FileConfiguration> | ||||||
| 			</File> | 			</File> | ||||||
|  | 			<File | ||||||
|  | 				RelativePath=".\System.cpp" | ||||||
|  | 				> | ||||||
|  | 			</File> | ||||||
| 			<File | 			<File | ||||||
| 				RelativePath="TrayWindow.cpp" | 				RelativePath="TrayWindow.cpp" | ||||||
| 				> | 				> | ||||||
| @@ -2877,6 +2881,10 @@ | |||||||
| 				RelativePath=".\StdAfx.h" | 				RelativePath=".\StdAfx.h" | ||||||
| 				> | 				> | ||||||
| 			</File> | 			</File> | ||||||
|  | 			<File | ||||||
|  | 				RelativePath=".\System.h" | ||||||
|  | 				> | ||||||
|  | 			</File> | ||||||
| 			<File | 			<File | ||||||
| 				RelativePath="TrayWindow.h" | 				RelativePath="TrayWindow.h" | ||||||
| 				> | 				> | ||||||
|   | |||||||
| @@ -682,6 +682,11 @@ void CMeasureNet::InitializeNewApi() | |||||||
| 			c_FreeMibTable = NULL; | 			c_FreeMibTable = NULL; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if (CRainmeter::GetDebug()) | ||||||
|  | 	{ | ||||||
|  | 		UpdateIFTable(); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|   | |||||||
| @@ -116,16 +116,34 @@ void CMeasurePlugin::ReadConfig(CConfigParser& parser, const WCHAR* section) | |||||||
| 	} | 	} | ||||||
| 	m_PluginName = Rainmeter->GetPluginPath() + m_PluginName; | 	m_PluginName = Rainmeter->GetPluginPath() + m_PluginName; | ||||||
|  |  | ||||||
|  | 	SetLastError(ERROR_SUCCESS); | ||||||
| 	m_Plugin = LoadLibrary(m_PluginName.c_str()); | 	m_Plugin = LoadLibrary(m_PluginName.c_str()); | ||||||
| 	 | 	 | ||||||
| 	if(m_Plugin == NULL) | 	if(m_Plugin == NULL) | ||||||
| 	{ | 	{ | ||||||
|  | 		if (CRainmeter::GetDebug()) | ||||||
|  | 		{ | ||||||
|  | 			DWORD err = GetLastError(); | ||||||
|  | 			DebugLog(L"Plugin: Unable to load plugin: \"%s\", ErrorCode=%i", m_PluginName.c_str(), err); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		// Try to load from Rainmeter's folder | 		// Try to load from Rainmeter's folder | ||||||
| 		pos = m_PluginName.rfind(L'\\'); | 		pos = m_PluginName.rfind(L'\\'); | ||||||
| 		if (pos != std::wstring::npos)  | 		if (pos != std::wstring::npos)  | ||||||
| 		{ | 		{ | ||||||
| 			std::wstring pluginName = Rainmeter->GetPath() + m_PluginName.substr(pos + 1); | 			std::wstring pluginName = Rainmeter->GetPath() + m_PluginName.substr(pos + 1); | ||||||
|  |  | ||||||
|  | 			SetLastError(ERROR_SUCCESS); | ||||||
| 			m_Plugin = LoadLibrary(pluginName.c_str()); | 			m_Plugin = LoadLibrary(pluginName.c_str()); | ||||||
|  |  | ||||||
|  | 			if (m_Plugin == NULL) | ||||||
|  | 			{ | ||||||
|  | 				if (CRainmeter::GetDebug()) | ||||||
|  | 				{ | ||||||
|  | 					DWORD err = GetLastError(); | ||||||
|  | 					DebugLog(L"Plugin: Unable to load plugin: \"%s\", ErrorCode=%i", pluginName.c_str(), err); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (m_Plugin == NULL) | 		if (m_Plugin == NULL) | ||||||
|   | |||||||
| @@ -643,10 +643,11 @@ bool CMeterImage::Draw(Graphics& graphics) | |||||||
| 			drawH = m_H; | 			drawH = m_H; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		//if (m_AntiAlias && m_Rotate != 0.0f) | 		if (!m_AntiAlias) | ||||||
| 		//{ | 		{ | ||||||
| 		//	graphics.SetCompositingQuality(CompositingQualityHighQuality); | 			//graphics.SetInterpolationMode(InterpolationModeNearestNeighbor); | ||||||
| 		//} | 			graphics.SetPixelOffsetMode(PixelOffsetModeHalf); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		Rect r(x, y, drawW, drawH); | 		Rect r(x, y, drawW, drawH); | ||||||
| 		graphics.DrawImage(drawBitmap, r, 0, 0, imageW, imageH, UnitPixel); | 		graphics.DrawImage(drawBitmap, r, 0, 0, imageW, imageH, UnitPixel); | ||||||
|   | |||||||
| @@ -717,4 +717,60 @@ std::wstring StringToProper(std::wstring str) | |||||||
| 	return str;//return the converted string | 	return str;//return the converted string | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | ** EnumerateInstalledFontFamilies | ||||||
|  | ** | ||||||
|  | ** Static helper to log all installed font families. | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | void CMeterString::EnumerateInstalledFontFamilies() | ||||||
|  | { | ||||||
|  | 	INT fontCount; | ||||||
|  | 	InstalledFontCollection fontCollection; | ||||||
|  |  | ||||||
|  | 	if (Ok == fontCollection.GetLastStatus()) | ||||||
|  | 	{ | ||||||
|  | 		fontCount = fontCollection.GetFamilyCount(); | ||||||
|  | 		if (fontCount > 0) | ||||||
|  | 		{ | ||||||
|  | 			INT fontFound; | ||||||
|  |  | ||||||
|  | 			FontFamily* fontFamilies = new FontFamily[fontCount]; | ||||||
|  |  | ||||||
|  | 			if (Ok == fontCollection.GetFamilies(fontCount, fontFamilies, &fontFound)) | ||||||
|  | 			{ | ||||||
|  | 				std::wstring fonts; | ||||||
|  | 				for (INT i = 0; i < fontCount; i++) | ||||||
|  | 				{ | ||||||
|  | 					WCHAR familyName[LF_FACESIZE]; | ||||||
|  | 					if (Ok == fontFamilies[i].GetFamilyName(familyName)) | ||||||
|  | 					{ | ||||||
|  | 						fonts += familyName; | ||||||
|  | 					} | ||||||
|  | 					else | ||||||
|  | 					{ | ||||||
|  | 						fonts += L"***"; | ||||||
|  | 					} | ||||||
|  | 					fonts += L", "; | ||||||
|  | 				} | ||||||
|  | 				LSLog(LOG_DEBUG, L"Rainmeter", fonts.c_str()); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				LSLog(LOG_DEBUG, L"Rainmeter", L"Failed to enumerate installed font families: GetFamilies() failed."); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			delete [] fontFamilies; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			LSLog(LOG_DEBUG, L"Rainmeter", L"There are no installed font families!"); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		LSLog(LOG_DEBUG, L"Rainmeter", L"Failed to enumerate installed font families: InstalledFontCollection() failed."); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // EOF | // EOF | ||||||
|   | |||||||
| @@ -41,6 +41,7 @@ public: | |||||||
| 	virtual void BindMeasure(std::list<CMeasure*>& measures); | 	virtual void BindMeasure(std::list<CMeasure*>& measures); | ||||||
|  |  | ||||||
| 	static void FreeFontCache(); | 	static void FreeFontCache(); | ||||||
|  | 	static void EnumerateInstalledFontFamilies(); | ||||||
|  |  | ||||||
| private: | private: | ||||||
| 	enum TEXTSTYLE | 	enum TEXTSTYLE | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -99,8 +99,12 @@ enum BANGCOMMAND | |||||||
| 	BANG_SHOW, | 	BANG_SHOW, | ||||||
| 	BANG_HIDE, | 	BANG_HIDE, | ||||||
| 	BANG_TOGGLE, | 	BANG_TOGGLE, | ||||||
|  | 	BANG_SHOWFADE, | ||||||
|  | 	BANG_HIDEFADE, | ||||||
|  | 	BANG_TOGGLEFADE, | ||||||
| 	BANG_MOVE, | 	BANG_MOVE, | ||||||
| 	BANG_ZPOS, | 	BANG_ZPOS, | ||||||
|  | 	BANG_SETTRANSPARENCY, | ||||||
| 	BANG_LSHOOK, | 	BANG_LSHOOK, | ||||||
| 	BANG_ABOUT, | 	BANG_ABOUT, | ||||||
| 	BANG_MOVEMETER, | 	BANG_MOVEMETER, | ||||||
| @@ -109,26 +113,6 @@ enum BANGCOMMAND | |||||||
| 	BANG_SETVARIABLE | 	BANG_SETVARIABLE | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct MONITOR_INFO |  | ||||||
| { |  | ||||||
| 	bool active; |  | ||||||
| 	HMONITOR handle; |  | ||||||
| 	RECT screen; |  | ||||||
| 	RECT work; |  | ||||||
| 	WCHAR deviceName[32];					//Device name (E.g. "\\.\DISPLAY1") |  | ||||||
| 	WCHAR monitorName[128];					//Monitor name (E.g. "Generic Non-PnP Monitor") |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct MULTIMONITOR_INFO |  | ||||||
| { |  | ||||||
| 	bool useEnumDisplayDevices;				//If true, use EnumDisplayDevices function to obtain the multi-monitor information |  | ||||||
| 	bool useEnumDisplayMonitors;			//If true, use EnumDisplayMonitors function to obtain the multi-monitor information |  | ||||||
|  |  | ||||||
| 	int vsT, vsL, vsH, vsW;					//Coordinates of the top-left corner (vsT,vsL) and size (vsH,vsW) of the virtual screen |  | ||||||
| 	int primary;							//Index of the primary monitor |  | ||||||
| 	std::vector<MONITOR_INFO> monitors;		//Monitor information |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| class CRainmeter; | class CRainmeter; | ||||||
| class CMeasure; | class CMeasure; | ||||||
| class CMeter; | class CMeter; | ||||||
| @@ -200,11 +184,6 @@ public: | |||||||
|  |  | ||||||
| 	Gdiplus::PrivateFontCollection* GetPrivateFontCollection(){ return m_FontCollection; } | 	Gdiplus::PrivateFontCollection* GetPrivateFontCollection(){ return m_FontCollection; } | ||||||
|  |  | ||||||
| 	static const MULTIMONITOR_INFO& GetMultiMonitorInfo() { return c_Monitors; } |  | ||||||
| 	static void ClearMultiMonitorInfo() { c_Monitors.monitors.clear(); } |  | ||||||
| 	static size_t GetMonitorCount(); |  | ||||||
| 	static void UpdateWorkareaInfo(); |  | ||||||
|  |  | ||||||
| protected: | protected: | ||||||
| 	static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); | 	static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); | ||||||
|  |  | ||||||
| @@ -255,8 +234,7 @@ private: | |||||||
| 	void ShowWindowIfAppropriate(); | 	void ShowWindowIfAppropriate(); | ||||||
| 	bool DoAction(int x, int y, MOUSE mouse, bool test); | 	bool DoAction(int x, int y, MOUSE mouse, bool test); | ||||||
| 	bool ResizeWindow(bool reset); | 	bool ResizeWindow(bool reset); | ||||||
|  | 	void IgnoreAeroPeek(); | ||||||
| 	static void SetMultiMonitorInfo(); |  | ||||||
|  |  | ||||||
| 	CConfigParser m_Parser; | 	CConfigParser m_Parser; | ||||||
|  |  | ||||||
| @@ -360,8 +338,6 @@ private: | |||||||
|  |  | ||||||
| 	static int c_InstanceCount; | 	static int c_InstanceCount; | ||||||
|  |  | ||||||
| 	static MULTIMONITOR_INFO c_Monitors;		// Multi-Monitor info |  | ||||||
|  |  | ||||||
| 	Gdiplus::PrivateFontCollection* m_FontCollection; | 	Gdiplus::PrivateFontCollection* m_FontCollection; | ||||||
|  |  | ||||||
| 	bool m_MouseActionCursor; | 	bool m_MouseActionCursor; | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ | |||||||
|  |  | ||||||
| #include "StdAfx.h" | #include "StdAfx.h" | ||||||
| #include "Rainmeter.h" | #include "Rainmeter.h" | ||||||
|  | #include "System.h" | ||||||
| #include "Error.h" | #include "Error.h" | ||||||
| #include "AboutDialog.h" | #include "AboutDialog.h" | ||||||
| #include "MeasureNet.h" | #include "MeasureNet.h" | ||||||
| @@ -244,11 +245,55 @@ void BangWithArgs(BANGCOMMAND bang, const WCHAR* arg, size_t numOfArgs) | |||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				// No config defined -> apply to all. | 				// No config defined -> apply to all. | ||||||
|  |  | ||||||
|  | 				// Make the sending order by using order of the config sections | ||||||
|  | 				std::vector<std::wstring> sections; | ||||||
|  | 				{ | ||||||
|  | 					CConfigParser parser; | ||||||
|  | 					parser.Initialize(Rainmeter->GetIniFile().c_str(), Rainmeter); | ||||||
|  | 					sections = parser.GetSections(); | ||||||
|  | 				} | ||||||
|  | 				std::vector<CMeterWindow*> windows(sections.size(), NULL); | ||||||
|  | 				std::vector<CMeterWindow*> windowsMissing; | ||||||
|  |  | ||||||
| 				std::map<std::wstring, CMeterWindow*>::iterator iter = Rainmeter->GetAllMeterWindows().begin(); | 				std::map<std::wstring, CMeterWindow*>::iterator iter = Rainmeter->GetAllMeterWindows().begin(); | ||||||
|  |  | ||||||
| 				for (; iter != Rainmeter->GetAllMeterWindows().end(); iter++) | 				for (; iter != Rainmeter->GetAllMeterWindows().end(); iter++) | ||||||
| 				{ | 				{ | ||||||
| 					((*iter).second)->RunBang(bang, argument.c_str()); | 					CMeterWindow* window = (*iter).second; | ||||||
|  | 					bool find = false; | ||||||
|  |  | ||||||
|  | 					for (size_t i = 0; i < windows.size(); i++) | ||||||
|  | 					{ | ||||||
|  | 						if (windows[i] == NULL && wcsicmp(sections[i].c_str(), window->GetSkinName().c_str()) == 0) | ||||||
|  | 						{ | ||||||
|  | 							windows[i] = window; | ||||||
|  | 							find = true; | ||||||
|  | 							break; | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					if (!find)  // Not found for some reasons | ||||||
|  | 					{ | ||||||
|  | 						windowsMissing.push_back(window); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				// Apply to all | ||||||
|  | 				std::vector<CMeterWindow*>::const_reverse_iterator iter2 = windows.rbegin(); | ||||||
|  | 				for ( ; iter2 != windows.rend(); iter2++) | ||||||
|  | 				{ | ||||||
|  | 					if (*iter2) | ||||||
|  | 					{ | ||||||
|  | 						(*iter2)->RunBang(bang, argument.c_str()); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				for (size_t i = 0; i < windowsMissing.size(); i++) | ||||||
|  | 				{ | ||||||
|  | 					if (windowsMissing[i]) | ||||||
|  | 					{ | ||||||
|  | 						windowsMissing[i]->RunBang(bang, argument.c_str()); | ||||||
|  | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @@ -293,6 +338,39 @@ void RainmeterToggle(HWND, const char* arg) | |||||||
| 	BangWithArgs(BANG_TOGGLE, ConvertToWide(arg).c_str(), 0); | 	BangWithArgs(BANG_TOGGLE, ConvertToWide(arg).c_str(), 0); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | ** RainmeterHideFade | ||||||
|  | ** | ||||||
|  | ** Callback for the !RainmeterHideFade bang | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | void RainmeterHideFade(HWND, const char* arg) | ||||||
|  | { | ||||||
|  | 	BangWithArgs(BANG_HIDEFADE, ConvertToWide(arg).c_str(), 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | ** RainmeterShowFade | ||||||
|  | ** | ||||||
|  | ** Callback for the !RainmeterShowFade bang | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | void RainmeterShowFade(HWND, const char* arg) | ||||||
|  | { | ||||||
|  | 	BangWithArgs(BANG_SHOWFADE, ConvertToWide(arg).c_str(), 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | ** RainmeterToggleFade | ||||||
|  | ** | ||||||
|  | ** Callback for the !RainmeterToggleFade bang | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | void RainmeterToggleFade(HWND, const char* arg) | ||||||
|  | { | ||||||
|  | 	BangWithArgs(BANG_TOGGLEFADE, ConvertToWide(arg).c_str(), 0); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| ** RainmeterHideMeter | ** RainmeterHideMeter | ||||||
| ** | ** | ||||||
| @@ -511,6 +589,17 @@ void RainmeterZPos(HWND, const char* arg) | |||||||
| 	BangWithArgs(BANG_ZPOS, ConvertToWide(arg).c_str(), 1); | 	BangWithArgs(BANG_ZPOS, ConvertToWide(arg).c_str(), 1); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | ** RainmeterSetTransparency | ||||||
|  | ** | ||||||
|  | ** Callback for the !RainmeterSetTransparency bang | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | void RainmeterSetTransparency(HWND, const char* arg) | ||||||
|  | { | ||||||
|  | 	BangWithArgs(BANG_SETTRANSPARENCY, ConvertToWide(arg).c_str(), 1); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| ** RainmeterLsHook | ** RainmeterLsHook | ||||||
| ** | ** | ||||||
| @@ -662,6 +751,8 @@ CRainmeter::~CRainmeter() | |||||||
|  |  | ||||||
| 	CMeterString::FreeFontCache(); | 	CMeterString::FreeFontCache(); | ||||||
|  |  | ||||||
|  | 	CSystem::Finalize(); | ||||||
|  |  | ||||||
| 	GdiplusShutdown(m_GDIplusToken); | 	GdiplusShutdown(m_GDIplusToken); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -865,6 +956,18 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) | |||||||
| 		CheckSkinVersions(); | 		CheckSkinVersions(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Read Debug first | ||||||
|  | 	c_Debug = 0!=GetPrivateProfileInt(L"Rainmeter", L"Debug", 0, m_IniFile.c_str()); | ||||||
|  |  | ||||||
|  | 	CSystem::Initialize(Instance); | ||||||
|  | 	CMeasureNet::InitializeNewApi(); | ||||||
|  |  | ||||||
|  | 	if (c_Debug) | ||||||
|  | 	{ | ||||||
|  | 		LSLog(LOG_DEBUG, L"Rainmeter", L"Enumerating installed font families ..."); | ||||||
|  | 		CMeterString::EnumerateInstalledFontFamilies(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// Tray must exist before configs are read | 	// Tray must exist before configs are read | ||||||
| 	m_TrayWindow = new CTrayWindow(m_Instance); | 	m_TrayWindow = new CTrayWindow(m_Instance); | ||||||
|  |  | ||||||
| @@ -884,8 +987,6 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) | |||||||
| 		CheckUpdate(); | 		CheckUpdate(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	CMeasureNet::InitializeNewApi(); |  | ||||||
|  |  | ||||||
| 	ResetStats(); | 	ResetStats(); | ||||||
| 	ReadStats(); | 	ReadStats(); | ||||||
|  |  | ||||||
| @@ -915,6 +1016,9 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) | |||||||
| 		AddBangCommand("!RainmeterHide", RainmeterHide); | 		AddBangCommand("!RainmeterHide", RainmeterHide); | ||||||
| 		AddBangCommand("!RainmeterShow", RainmeterShow); | 		AddBangCommand("!RainmeterShow", RainmeterShow); | ||||||
| 		AddBangCommand("!RainmeterToggle", RainmeterToggle); | 		AddBangCommand("!RainmeterToggle", RainmeterToggle); | ||||||
|  | 		AddBangCommand("!RainmeterHideFade", RainmeterHideFade); | ||||||
|  | 		AddBangCommand("!RainmeterShowFade", RainmeterShowFade); | ||||||
|  | 		AddBangCommand("!RainmeterToggleFade", RainmeterToggleFade); | ||||||
| 		AddBangCommand("!RainmeterHideMeter", RainmeterHideMeter); | 		AddBangCommand("!RainmeterHideMeter", RainmeterHideMeter); | ||||||
| 		AddBangCommand("!RainmeterShowMeter", RainmeterShowMeter); | 		AddBangCommand("!RainmeterShowMeter", RainmeterShowMeter); | ||||||
| 		AddBangCommand("!RainmeterToggleMeter", RainmeterToggleMeter); | 		AddBangCommand("!RainmeterToggleMeter", RainmeterToggleMeter); | ||||||
| @@ -926,6 +1030,7 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) | |||||||
| 		AddBangCommand("!RainmeterDeactivateConfig", RainmeterDeactivateConfig); | 		AddBangCommand("!RainmeterDeactivateConfig", RainmeterDeactivateConfig); | ||||||
| 		AddBangCommand("!RainmeterMove", RainmeterMove); | 		AddBangCommand("!RainmeterMove", RainmeterMove); | ||||||
| 		AddBangCommand("!RainmeterZPos", RainmeterZPos); | 		AddBangCommand("!RainmeterZPos", RainmeterZPos); | ||||||
|  | 		AddBangCommand("!RainmeterSetTransparency", RainmeterSetTransparency); | ||||||
| 		AddBangCommand("!RainmeterLsBoxHook", RainmeterLsHook); | 		AddBangCommand("!RainmeterLsBoxHook", RainmeterLsHook); | ||||||
| 		AddBangCommand("!RainmeterAbout", RainmeterAbout); | 		AddBangCommand("!RainmeterAbout", RainmeterAbout); | ||||||
| 		AddBangCommand("!RainmeterResetStats", RainmeterResetStats); | 		AddBangCommand("!RainmeterResetStats", RainmeterResetStats); | ||||||
| @@ -935,12 +1040,54 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) | |||||||
| 		AddBangCommand("!RainmeterSetVariable", RainmeterSetVariable); | 		AddBangCommand("!RainmeterSetVariable", RainmeterSetVariable); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Create meter windows for active configs | 	// Make the starting order by using order of the config sections | ||||||
|  | 	std::vector<std::wstring> sections; | ||||||
|  | 	{ | ||||||
|  | 		CConfigParser parser; | ||||||
|  | 		parser.Initialize(m_IniFile.c_str(), this); | ||||||
|  | 		sections = parser.GetSections(); | ||||||
|  | 	} | ||||||
|  | 	std::vector<std::pair<int, int> > startup(sections.size(), std::pair<int, int>(0, 0)); | ||||||
|  | 	std::vector<std::pair<int, int> > startupMissing; | ||||||
|  |  | ||||||
| 	for (size_t i = 0; i < m_ConfigStrings.size(); i++) | 	for (size_t i = 0; i < m_ConfigStrings.size(); i++) | ||||||
| 	{ | 	{ | ||||||
| 		if (m_ConfigStrings[i].active > 0 && m_ConfigStrings[i].active <= (int)m_ConfigStrings[i].iniFiles.size()) | 		if (m_ConfigStrings[i].active > 0 && m_ConfigStrings[i].active <= (int)m_ConfigStrings[i].iniFiles.size()) | ||||||
| 		{ | 		{ | ||||||
| 			ActivateConfig(i, m_ConfigStrings[i].active - 1); | 			bool find = false; | ||||||
|  |  | ||||||
|  | 			for (size_t j = 0; j < startup.size(); j++) | ||||||
|  | 			{ | ||||||
|  | 				if (startup[j].second == 0 && wcsicmp(sections[j].c_str(), m_ConfigStrings[i].config.c_str()) == 0) | ||||||
|  | 				{ | ||||||
|  | 					startup[j].first = i; | ||||||
|  | 					startup[j].second = m_ConfigStrings[i].active; | ||||||
|  | 					find = true; | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (!find)  // Not found for some reasons | ||||||
|  | 			{ | ||||||
|  | 				startupMissing.push_back(std::pair<int, int>(i, m_ConfigStrings[i].active)); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Create meter windows for active configs | ||||||
|  | 	std::vector<std::pair<int, int> >::const_reverse_iterator iter = startup.rbegin(); | ||||||
|  | 	for ( ; iter != startup.rend(); iter++) | ||||||
|  | 	{ | ||||||
|  | 		if ((*iter).second > 0) | ||||||
|  | 		{ | ||||||
|  | 			ActivateConfig((*iter).first, (*iter).second - 1); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	for (size_t i = 0; i < startupMissing.size(); i++) | ||||||
|  | 	{ | ||||||
|  | 		if (startupMissing[i].second > 0) | ||||||
|  | 		{ | ||||||
|  | 			ActivateConfig(startupMissing[i].first, startupMissing[i].second - 1); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -1278,7 +1425,8 @@ bool CRainmeter::DeleteMeterWindow(CMeterWindow* meterWindow, bool bLater) | |||||||
| 	if (bLater) | 	if (bLater) | ||||||
| 	{ | 	{ | ||||||
| 		m_DelayDeleteList.push_back(meterWindow); | 		m_DelayDeleteList.push_back(meterWindow); | ||||||
| 		meterWindow->FadeWindow(meterWindow->GetAlphaValue(), 0);	// Fade out the window | 		meterWindow->RunBang(BANG_HIDEFADE, NULL);	// Fade out the window | ||||||
|  | 		//meterWindow->FadeWindow(meterWindow->GetAlphaValue(), 0);	// Fade out the window | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| @@ -1344,6 +1492,9 @@ void CRainmeter::Quit(HINSTANCE dllInst) | |||||||
| 		RemoveBangCommand("!RainmeterHide"); | 		RemoveBangCommand("!RainmeterHide"); | ||||||
| 		RemoveBangCommand("!RainmeterShow"); | 		RemoveBangCommand("!RainmeterShow"); | ||||||
| 		RemoveBangCommand("!RainmeterToggle"); | 		RemoveBangCommand("!RainmeterToggle"); | ||||||
|  | 		RemoveBangCommand("!RainmeterHideFade"); | ||||||
|  | 		RemoveBangCommand("!RainmeterShowFade"); | ||||||
|  | 		RemoveBangCommand("!RainmeterToggleFade"); | ||||||
| 		RemoveBangCommand("!RainmeterHideMeter"); | 		RemoveBangCommand("!RainmeterHideMeter"); | ||||||
| 		RemoveBangCommand("!RainmeterShowMeter"); | 		RemoveBangCommand("!RainmeterShowMeter"); | ||||||
| 		RemoveBangCommand("!RainmeterToggleMeter"); | 		RemoveBangCommand("!RainmeterToggleMeter"); | ||||||
| @@ -1355,6 +1506,7 @@ void CRainmeter::Quit(HINSTANCE dllInst) | |||||||
| 		RemoveBangCommand("!RainmeterToggleConfig"); | 		RemoveBangCommand("!RainmeterToggleConfig"); | ||||||
| 		RemoveBangCommand("!RainmeterMove"); | 		RemoveBangCommand("!RainmeterMove"); | ||||||
| 		RemoveBangCommand("!RainmeterZPos"); | 		RemoveBangCommand("!RainmeterZPos"); | ||||||
|  | 		RemoveBangCommand("!RainmeterSetTransparency"); | ||||||
| 		RemoveBangCommand("!RainmeterLsBoxHook"); | 		RemoveBangCommand("!RainmeterLsBoxHook"); | ||||||
| 		RemoveBangCommand("!RainmeterAbout"); | 		RemoveBangCommand("!RainmeterAbout"); | ||||||
| 		RemoveBangCommand("!RainmeterResetStats"); | 		RemoveBangCommand("!RainmeterResetStats"); | ||||||
| @@ -1518,6 +1670,18 @@ BOOL CRainmeter::ExecuteBang(const std::wstring& bang, const std::wstring& arg, | |||||||
| 	{ | 	{ | ||||||
| 		BangWithArgs(BANG_TOGGLE, arg.c_str(), 0); | 		BangWithArgs(BANG_TOGGLE, arg.c_str(), 0); | ||||||
| 	} | 	} | ||||||
|  | 	else if (wcsicmp(bang.c_str(), L"!RainmeterHideFade") == 0) | ||||||
|  | 	{ | ||||||
|  | 		BangWithArgs(BANG_HIDEFADE, arg.c_str(), 0); | ||||||
|  | 	} | ||||||
|  | 	else if (wcsicmp(bang.c_str(), L"!RainmeterShowFade") == 0) | ||||||
|  | 	{ | ||||||
|  | 		BangWithArgs(BANG_SHOWFADE, arg.c_str(), 0); | ||||||
|  | 	} | ||||||
|  | 	else if (wcsicmp(bang.c_str(), L"!RainmeterToggleFade") == 0) | ||||||
|  | 	{ | ||||||
|  | 		BangWithArgs(BANG_TOGGLEFADE, arg.c_str(), 0); | ||||||
|  | 	} | ||||||
| 	else if (wcsicmp(bang.c_str(), L"!RainmeterHideMeter") == 0) | 	else if (wcsicmp(bang.c_str(), L"!RainmeterHideMeter") == 0) | ||||||
| 	{ | 	{ | ||||||
| 		BangWithArgs(BANG_HIDEMETER, arg.c_str(), 1); | 		BangWithArgs(BANG_HIDEMETER, arg.c_str(), 1); | ||||||
| @@ -1566,6 +1730,10 @@ BOOL CRainmeter::ExecuteBang(const std::wstring& bang, const std::wstring& arg, | |||||||
| 	{ | 	{ | ||||||
| 		BangWithArgs(BANG_ZPOS, arg.c_str(), 1); | 		BangWithArgs(BANG_ZPOS, arg.c_str(), 1); | ||||||
| 	} | 	} | ||||||
|  | 	else if (wcsicmp(bang.c_str(), L"!RainmeterSetTransparency") == 0) | ||||||
|  | 	{ | ||||||
|  | 		BangWithArgs(BANG_SETTRANSPARENCY, arg.c_str(), 1); | ||||||
|  | 	} | ||||||
| 	else if (wcsicmp(bang.c_str(), L"!RainmeterAbout") == 0) | 	else if (wcsicmp(bang.c_str(), L"!RainmeterAbout") == 0) | ||||||
| 	{ | 	{ | ||||||
| 		BangWithArgs(BANG_ABOUT, arg.c_str(), 0); | 		BangWithArgs(BANG_ABOUT, arg.c_str(), 0); | ||||||
| @@ -1778,9 +1946,6 @@ void CRainmeter::ExecuteCommand(const WCHAR* command, CMeterWindow* meterWindow) | |||||||
| */ | */ | ||||||
| void CRainmeter::ReadGeneralSettings(std::wstring& iniFile) | void CRainmeter::ReadGeneralSettings(std::wstring& iniFile) | ||||||
| { | { | ||||||
| 	// Read Debug first |  | ||||||
| 	c_Debug = 0!=GetPrivateProfileInt(L"Rainmeter", L"Debug", 0, iniFile.c_str()); |  | ||||||
|  |  | ||||||
| 	CConfigParser parser; | 	CConfigParser parser; | ||||||
| 	parser.Initialize(iniFile.c_str(), this); | 	parser.Initialize(iniFile.c_str(), this); | ||||||
|  |  | ||||||
| @@ -1891,34 +2056,34 @@ bool CRainmeter::SetActiveConfig(std::wstring& skinName, std::wstring& skinIni) | |||||||
| ** Refreshes Rainmeter. If argument is given the config is refreshed | ** Refreshes Rainmeter. If argument is given the config is refreshed | ||||||
| ** otherwise all active meters are refreshed | ** otherwise all active meters are refreshed | ||||||
| */ | */ | ||||||
| void CRainmeter::Refresh(const WCHAR* arg) | //void CRainmeter::Refresh(const WCHAR* arg) | ||||||
| { | //{ | ||||||
| 	std::wstring config, iniFile; | //	std::wstring config, iniFile; | ||||||
|  | // | ||||||
| 	try  | //	try  | ||||||
| 	{ | //	{ | ||||||
| 		if (arg != NULL && wcslen(arg) > 0)  | //		if (arg != NULL && wcslen(arg) > 0)  | ||||||
| 		{ | //		{ | ||||||
| 			std::wstring config = arg; | //			std::wstring config = arg; | ||||||
| 			CMeterWindow* meterWindow = GetMeterWindow(config); | //			CMeterWindow* meterWindow = GetMeterWindow(config); | ||||||
| 			meterWindow->Refresh(false); | //			meterWindow->Refresh(false); | ||||||
| 		} | //		} | ||||||
| 		else | //		else | ||||||
| 		{ | //		{ | ||||||
| 			std::map<std::wstring, CMeterWindow*>::iterator iter = m_Meters.begin(); | //			std::map<std::wstring, CMeterWindow*>::iterator iter = m_Meters.begin(); | ||||||
|  | // | ||||||
| 			// Refresh all | //			// Refresh all | ||||||
| 			for (; iter != m_Meters.end(); iter++) | //			for (; iter != m_Meters.end(); iter++) | ||||||
| 			{ | //			{ | ||||||
| 				(*iter).second->Refresh(false); | //				(*iter).second->Refresh(false); | ||||||
| 			} | //			} | ||||||
| 		} | //		} | ||||||
| 	}  | //	}  | ||||||
| 	catch(CError& error)  | //	catch(CError& error)  | ||||||
| 	{ | //	{ | ||||||
| 		MessageBox(NULL, error.GetString().c_str(), APPNAME, MB_OK | MB_TOPMOST | MB_ICONEXCLAMATION); | //		MessageBox(NULL, error.GetString().c_str(), APPNAME, MB_OK | MB_TOPMOST | MB_ICONEXCLAMATION); | ||||||
| 	} | //	} | ||||||
| } | //} | ||||||
|  |  | ||||||
| /* | /* | ||||||
| ** ReadStats | ** ReadStats | ||||||
| @@ -2313,11 +2478,11 @@ HMENU CRainmeter::CreateMonitorMenu(CMeterWindow* meterWindow) | |||||||
| 	AppendMenu(monitorMenu, flags, ID_MONITOR_FIRST, L"@0: Virtual screen"); | 	AppendMenu(monitorMenu, flags, ID_MONITOR_FIRST, L"@0: Virtual screen"); | ||||||
|  |  | ||||||
| 	// for the "Specified monitor" (@n) | 	// for the "Specified monitor" (@n) | ||||||
| 	if (CMeterWindow::GetMonitorCount() > 0) | 	if (CSystem::GetMonitorCount() > 0) | ||||||
| 	{ | 	{ | ||||||
| 		AppendMenu(monitorMenu, MF_SEPARATOR, 0, NULL); | 		AppendMenu(monitorMenu, MF_SEPARATOR, 0, NULL); | ||||||
|  |  | ||||||
| 		const MULTIMONITOR_INFO& multimonInfo = CMeterWindow::GetMultiMonitorInfo(); | 		const MULTIMONITOR_INFO& multimonInfo = CSystem::GetMultiMonitorInfo(); | ||||||
| 		const std::vector<MONITOR_INFO>& monitors = multimonInfo.monitors; | 		const std::vector<MONITOR_INFO>& monitors = multimonInfo.monitors; | ||||||
|  |  | ||||||
| 		for (size_t i = 0; i < monitors.size(); i++) | 		for (size_t i = 0; i < monitors.size(); i++) | ||||||
|   | |||||||
| @@ -175,7 +175,7 @@ private: | |||||||
| 	void ScanForThemes(std::wstring& path); | 	void ScanForThemes(std::wstring& path); | ||||||
| 	void ReadGeneralSettings(std::wstring& path); | 	void ReadGeneralSettings(std::wstring& path); | ||||||
| 	bool SetActiveConfig(std::wstring& skinName, std::wstring& skinIni); | 	bool SetActiveConfig(std::wstring& skinName, std::wstring& skinIni); | ||||||
| 	void Refresh(const WCHAR* arg); | 	//void Refresh(const WCHAR* arg); | ||||||
| 	HMENU CreateSkinMenu(CMeterWindow* meterWindow, int index); | 	HMENU CreateSkinMenu(CMeterWindow* meterWindow, int index); | ||||||
| 	void ChangeSkinIndex(HMENU subMenu, int index); | 	void ChangeSkinIndex(HMENU subMenu, int index); | ||||||
| 	int ScanForConfigsRecursive(std::wstring& path, std::wstring base, int index, std::vector<CONFIGMENU>& menu, bool DontRecurse); | 	int ScanForConfigsRecursive(std::wstring& path, std::wstring base, int index, std::vector<CONFIGMENU>& menu, bool DontRecurse); | ||||||
|   | |||||||
							
								
								
									
										793
									
								
								Library/System.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										793
									
								
								Library/System.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,793 @@ | |||||||
|  | /* | ||||||
|  |   Copyright (C) 2010 spx | ||||||
|  |  | ||||||
|  |   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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | #include "StdAfx.h" | ||||||
|  | #include "System.h" | ||||||
|  | #include "Litestep.h" | ||||||
|  | #include "Rainmeter.h" | ||||||
|  | #include "Error.h" | ||||||
|  |  | ||||||
|  | enum TIMER | ||||||
|  | { | ||||||
|  | 	TIMER_SHOWDESKTOP = 1, | ||||||
|  | 	TIMER_COMPOSITION = 2 | ||||||
|  | }; | ||||||
|  | enum INTERVAL | ||||||
|  | { | ||||||
|  | 	INTERVAL_SHOWDESKTOP = 250, | ||||||
|  | 	INTERVAL_COMPOSITION = 250 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | MULTIMONITOR_INFO CSystem::c_Monitors = { 0 }; | ||||||
|  |  | ||||||
|  | HWND CSystem::c_Window = NULL; | ||||||
|  | bool CSystem::c_DwmCompositionEnabled = false; | ||||||
|  | bool CSystem::c_ShowDesktop = false; | ||||||
|  |  | ||||||
|  | extern CRainmeter* Rainmeter; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | ** Initialize | ||||||
|  | ** | ||||||
|  | ** Creates a window to detect changes in the system. | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | void CSystem::Initialize(HINSTANCE instance) | ||||||
|  | { | ||||||
|  | 	WNDCLASS wc = {0}; | ||||||
|  | 	wc.lpfnWndProc = (WNDPROC)WndProc; | ||||||
|  | 	wc.hInstance = instance; | ||||||
|  | 	wc.lpszClassName = L"RainmeterSystemClass"; | ||||||
|  |  | ||||||
|  | 	RegisterClass(&wc); | ||||||
|  |  | ||||||
|  | 	c_Window = CreateWindowEx( | ||||||
|  | 		WS_EX_TOOLWINDOW, | ||||||
|  | 		L"RainmeterSystemClass", | ||||||
|  | 		NULL, | ||||||
|  | 		WS_POPUP, | ||||||
|  | 		CW_USEDEFAULT, | ||||||
|  | 		CW_USEDEFAULT, | ||||||
|  | 		CW_USEDEFAULT, | ||||||
|  | 		CW_USEDEFAULT, | ||||||
|  | 		NULL, | ||||||
|  | 		NULL, | ||||||
|  | 		instance, | ||||||
|  | 		NULL); | ||||||
|  |  | ||||||
|  | 	SetWindowPos(c_Window, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); | ||||||
|  |  | ||||||
|  | #ifndef _WIN64 | ||||||
|  | 	SetWindowLong(c_Window, GWL_USERDATA, magicDWord); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	SetMultiMonitorInfo(); | ||||||
|  |  | ||||||
|  | 	c_DwmCompositionEnabled = (DwmIsCompositionEnabled() == TRUE); | ||||||
|  | 	if (c_DwmCompositionEnabled) | ||||||
|  | 	{ | ||||||
|  | 		SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_SHOWDESKTOP, NULL); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | ** Finalize | ||||||
|  | ** | ||||||
|  | ** Destroys a window. | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | void CSystem::Finalize() | ||||||
|  | { | ||||||
|  | 	KillTimer(c_Window, TIMER_SHOWDESKTOP); | ||||||
|  | 	KillTimer(c_Window, TIMER_COMPOSITION); | ||||||
|  |  | ||||||
|  | 	if (c_Window) DestroyWindow(c_Window); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* MyInfoEnumProc | ||||||
|  | ** | ||||||
|  | ** Retrieves the multi-monitor information. | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | BOOL CALLBACK MyInfoEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) | ||||||
|  | { | ||||||
|  | 	MULTIMONITOR_INFO* m = (MULTIMONITOR_INFO*)dwData; | ||||||
|  |  | ||||||
|  | 	MONITORINFOEX info; | ||||||
|  | 	info.cbSize = sizeof(MONITORINFOEX); | ||||||
|  | 	GetMonitorInfo(hMonitor, &info); | ||||||
|  |  | ||||||
|  | 	if (CRainmeter::GetDebug()) | ||||||
|  | 	{ | ||||||
|  | 		DebugLog(info.szDevice); | ||||||
|  | 		DebugLog(L"  Flags    : %s(0x%08X)", (info.dwFlags & MONITORINFOF_PRIMARY) ? L"PRIMARY " : L"", info.dwFlags); | ||||||
|  | 		DebugLog(L"  Handle   : 0x%08X", hMonitor); | ||||||
|  | 		DebugLog(L"  ScrArea  : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", | ||||||
|  | 			lprcMonitor->left, lprcMonitor->top, lprcMonitor->right, lprcMonitor->bottom, | ||||||
|  | 			lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top); | ||||||
|  | 		DebugLog(L"  WorkArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", | ||||||
|  | 			info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, | ||||||
|  | 			info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); | ||||||
|  | 	} | ||||||
|  | 	if (m == NULL) return TRUE; | ||||||
|  |  | ||||||
|  | 	if (m->useEnumDisplayDevices) | ||||||
|  | 	{ | ||||||
|  | 		for (size_t i = 0; i < m->monitors.size(); i++) | ||||||
|  | 		{ | ||||||
|  | 			if (m->monitors[i].handle == NULL && _wcsnicmp(info.szDevice, m->monitors[i].deviceName, 32) == 0) | ||||||
|  | 			{ | ||||||
|  | 				m->monitors[i].handle = hMonitor; | ||||||
|  | 				m->monitors[i].screen = *lprcMonitor; | ||||||
|  | 				m->monitors[i].work = info.rcWork; | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else  // use only EnumDisplayMonitors | ||||||
|  | 	{ | ||||||
|  | 		MONITOR_INFO monitor = {0}; | ||||||
|  | 		monitor.active = true; | ||||||
|  |  | ||||||
|  | 		monitor.handle = hMonitor; | ||||||
|  | 		monitor.screen = *lprcMonitor; | ||||||
|  | 		monitor.work = info.rcWork; | ||||||
|  |  | ||||||
|  | 		wcsncpy(monitor.deviceName, info.szDevice, 32);  // E.g. "\\.\DISPLAY1" | ||||||
|  |  | ||||||
|  | 		// Get the monitor name (E.g. "Generic Non-PnP Monitor") | ||||||
|  | 		DISPLAY_DEVICE ddm = {0}; | ||||||
|  | 		ddm.cb = sizeof(DISPLAY_DEVICE); | ||||||
|  | 		DWORD dwMon = 0; | ||||||
|  | 		while (EnumDisplayDevices(info.szDevice, dwMon++, &ddm, 0)) | ||||||
|  | 		{ | ||||||
|  | 			if (ddm.StateFlags & DISPLAY_DEVICE_ACTIVE && ddm.StateFlags & DISPLAY_DEVICE_ATTACHED) | ||||||
|  | 			{ | ||||||
|  | 				wcsncpy(monitor.monitorName, ddm.DeviceString, 128); | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		m->monitors.push_back(monitor); | ||||||
|  |  | ||||||
|  | 		if (info.dwFlags & MONITORINFOF_PRIMARY) | ||||||
|  | 		{ | ||||||
|  | 			// It's primary monitor! | ||||||
|  | 			m->primary = (int)m->monitors.size(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return TRUE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* GetMonitorCount | ||||||
|  | ** | ||||||
|  | ** Returns the number of monitors. | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | size_t CSystem::GetMonitorCount() | ||||||
|  | { | ||||||
|  | 	if (c_Monitors.monitors.size() == 0) | ||||||
|  | 	{ | ||||||
|  | 		SetMultiMonitorInfo(); | ||||||
|  | 	} | ||||||
|  | 	return c_Monitors.monitors.size(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* SetMultiMonitorInfo | ||||||
|  | ** | ||||||
|  | ** Sets the multi-monitor information. | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | void CSystem::SetMultiMonitorInfo() | ||||||
|  | { | ||||||
|  | 	std::vector<MONITOR_INFO>& monitors = c_Monitors.monitors; | ||||||
|  | 	bool logging = CRainmeter::GetDebug(); | ||||||
|  |  | ||||||
|  | 	if (monitors.capacity() < 16) { monitors.reserve(16); } | ||||||
|  |  | ||||||
|  | 	c_Monitors.vsT = GetSystemMetrics(SM_YVIRTUALSCREEN); | ||||||
|  | 	c_Monitors.vsL = GetSystemMetrics(SM_XVIRTUALSCREEN); | ||||||
|  | 	c_Monitors.vsH = GetSystemMetrics(SM_CYVIRTUALSCREEN); | ||||||
|  | 	c_Monitors.vsW = GetSystemMetrics(SM_CXVIRTUALSCREEN); | ||||||
|  |  | ||||||
|  | 	c_Monitors.primary = 1;  // If primary screen is not found, 1st screen is assumed as primary screen. | ||||||
|  |  | ||||||
|  | 	c_Monitors.useEnumDisplayDevices = true; | ||||||
|  | 	c_Monitors.useEnumDisplayMonitors = false; | ||||||
|  |  | ||||||
|  | 	if (logging) | ||||||
|  | 	{ | ||||||
|  | 		DebugLog(L"------------------------------"); | ||||||
|  | 		DebugLog(L"* EnumDisplayDevices / EnumDisplaySettings API"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	DISPLAY_DEVICE dd = {0}; | ||||||
|  | 	dd.cb = sizeof(DISPLAY_DEVICE); | ||||||
|  |  | ||||||
|  | 	if (EnumDisplayDevices(NULL, 0, &dd, 0)) | ||||||
|  | 	{ | ||||||
|  | 		DWORD dwDevice = 0; | ||||||
|  |  | ||||||
|  | 		do | ||||||
|  | 		{ | ||||||
|  | 			std::wstring msg; | ||||||
|  |  | ||||||
|  | 			if (logging) | ||||||
|  | 			{ | ||||||
|  | 				DebugLog(dd.DeviceName); | ||||||
|  |  | ||||||
|  | 				if (dd.StateFlags & DISPLAY_DEVICE_ACTIVE) | ||||||
|  | 				{ | ||||||
|  | 					msg += L"ACTIVE "; | ||||||
|  | 				} | ||||||
|  | 				if (dd.StateFlags & DISPLAY_DEVICE_MULTI_DRIVER) | ||||||
|  | 				{ | ||||||
|  | 					msg += L"MULTI "; | ||||||
|  | 				} | ||||||
|  | 				if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) | ||||||
|  | 				{ | ||||||
|  | 					msg += L"PRIMARY "; | ||||||
|  | 				} | ||||||
|  | 				if (dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) | ||||||
|  | 				{ | ||||||
|  | 					msg += L"MIRROR "; | ||||||
|  | 				} | ||||||
|  | 				if (dd.StateFlags & DISPLAY_DEVICE_VGA_COMPATIBLE) | ||||||
|  | 				{ | ||||||
|  | 					msg += L"VGA "; | ||||||
|  | 				} | ||||||
|  | 				if (dd.StateFlags & DISPLAY_DEVICE_REMOVABLE) | ||||||
|  | 				{ | ||||||
|  | 					msg += L"REMOVABLE "; | ||||||
|  | 				} | ||||||
|  | 				if (dd.StateFlags & DISPLAY_DEVICE_MODESPRUNED) | ||||||
|  | 				{ | ||||||
|  | 					msg += L"PRUNED "; | ||||||
|  | 				} | ||||||
|  | 				if (dd.StateFlags & DISPLAY_DEVICE_REMOTE) | ||||||
|  | 				{ | ||||||
|  | 					msg += L"REMOTE "; | ||||||
|  | 				} | ||||||
|  | 				if (dd.StateFlags & DISPLAY_DEVICE_DISCONNECT) | ||||||
|  | 				{ | ||||||
|  | 					msg += L"DISCONNECT "; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if ((dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) == 0) | ||||||
|  | 			{ | ||||||
|  | 				MONITOR_INFO monitor = {0}; | ||||||
|  |  | ||||||
|  | 				monitor.handle = NULL; | ||||||
|  | 				wcsncpy(monitor.deviceName, dd.DeviceName, 32);  // E.g. "\\.\DISPLAY1" | ||||||
|  |  | ||||||
|  | 				// Get the monitor name (E.g. "Generic Non-PnP Monitor") | ||||||
|  | 				DISPLAY_DEVICE ddm = {0}; | ||||||
|  | 				ddm.cb = sizeof(DISPLAY_DEVICE); | ||||||
|  | 				DWORD dwMon = 0; | ||||||
|  | 				while (EnumDisplayDevices(dd.DeviceName, dwMon++, &ddm, 0)) | ||||||
|  | 				{ | ||||||
|  | 					if (ddm.StateFlags & DISPLAY_DEVICE_ACTIVE && ddm.StateFlags & DISPLAY_DEVICE_ATTACHED) | ||||||
|  | 					{ | ||||||
|  | 						wcsncpy(monitor.monitorName, ddm.DeviceString, 128); | ||||||
|  |  | ||||||
|  | 						if (logging) | ||||||
|  | 						{ | ||||||
|  | 							DebugLog(L"  Name     : %s", ddm.DeviceString); | ||||||
|  | 						} | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if (logging) | ||||||
|  | 				{ | ||||||
|  | 					DebugLog(L"  Adapter  : %s", dd.DeviceString); | ||||||
|  | 					DebugLog(L"  Flags    : %s(0x%08X)", msg.c_str(), dd.StateFlags); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if (dd.StateFlags & DISPLAY_DEVICE_ACTIVE) | ||||||
|  | 				{ | ||||||
|  | 					monitor.active = true; | ||||||
|  |  | ||||||
|  | 					DEVMODE dm = {0}; | ||||||
|  | 					dm.dmSize = sizeof(DEVMODE); | ||||||
|  |  | ||||||
|  | 					if (EnumDisplaySettings(dd.DeviceName, ENUM_CURRENT_SETTINGS, &dm)) | ||||||
|  | 					{ | ||||||
|  | 						POINT pos = {dm.dmPosition.x, dm.dmPosition.y}; | ||||||
|  | 						monitor.handle = MonitorFromPoint(pos, MONITOR_DEFAULTTONULL); | ||||||
|  |  | ||||||
|  | 						if (logging) | ||||||
|  | 						{ | ||||||
|  | 							DebugLog(L"  Handle   : 0x%08X", monitor.handle); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					if (monitor.handle != NULL) | ||||||
|  | 					{ | ||||||
|  | 						MONITORINFO info = {0}; | ||||||
|  | 						info.cbSize = sizeof(MONITORINFO); | ||||||
|  | 						GetMonitorInfo(monitor.handle, &info); | ||||||
|  |  | ||||||
|  | 						monitor.screen = info.rcMonitor; | ||||||
|  | 						monitor.work = info.rcWork; | ||||||
|  |  | ||||||
|  | 						if (logging) | ||||||
|  | 						{ | ||||||
|  | 							DebugLog(L"  ScrArea  : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", | ||||||
|  | 								info.rcMonitor.left, info.rcMonitor.top, info.rcMonitor.right, info.rcMonitor.bottom, | ||||||
|  | 								info.rcMonitor.right - info.rcMonitor.left, info.rcMonitor.bottom - info.rcMonitor.top); | ||||||
|  | 							DebugLog(L"  WorkArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", | ||||||
|  | 								info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, | ||||||
|  | 								info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					else  // monitor not found | ||||||
|  | 					{ | ||||||
|  | 						c_Monitors.useEnumDisplayMonitors = true; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				else | ||||||
|  | 				{ | ||||||
|  | 					monitor.active = false; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				monitors.push_back(monitor); | ||||||
|  |  | ||||||
|  | 				if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) | ||||||
|  | 				{ | ||||||
|  | 					// It's primary monitor! | ||||||
|  | 					c_Monitors.primary = (int)monitors.size(); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				if (logging) | ||||||
|  | 				{ | ||||||
|  | 					DebugLog(L"  Adapter  : %s", dd.DeviceString); | ||||||
|  | 					DebugLog(L"  Flags    : %s(0x%08X)", msg.c_str(), dd.StateFlags); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			dwDevice++; | ||||||
|  | 		} while (EnumDisplayDevices(NULL, dwDevice, &dd, 0)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (monitors.empty())  // Failed to enumerate the non-mirroring monitors | ||||||
|  | 	{ | ||||||
|  | 		DebugLog(L"Failed to enumerate the non-mirroring monitors. Only EnumDisplayMonitors is used instead."); | ||||||
|  | 		c_Monitors.useEnumDisplayDevices = false; | ||||||
|  | 		c_Monitors.useEnumDisplayMonitors = true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (logging) | ||||||
|  | 	{ | ||||||
|  | 		DebugLog(L"------------------------------"); | ||||||
|  | 		DebugLog(L"* EnumDisplayMonitors API"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (c_Monitors.useEnumDisplayMonitors) | ||||||
|  | 	{ | ||||||
|  | 		EnumDisplayMonitors(NULL, NULL, MyInfoEnumProc, (LPARAM)(&c_Monitors)); | ||||||
|  |  | ||||||
|  | 		if (monitors.empty())  // Failed to enumerate the monitors | ||||||
|  | 		{ | ||||||
|  | 			DebugLog(L"Failed to enumerate the monitors. Prepares the dummy monitor information."); | ||||||
|  | 			c_Monitors.useEnumDisplayMonitors = false; | ||||||
|  |  | ||||||
|  | 			MONITOR_INFO monitor = {0}; | ||||||
|  | 			wcscpy(monitor.deviceName, L"DUMMY"); | ||||||
|  | 			POINT pos = {0, 0}; | ||||||
|  | 			monitor.handle = MonitorFromPoint(pos, MONITOR_DEFAULTTOPRIMARY); | ||||||
|  | 			monitor.screen.left = 0; | ||||||
|  | 			monitor.screen.top = 0; | ||||||
|  | 			monitor.screen.right = GetSystemMetrics(SM_CXSCREEN); | ||||||
|  | 			monitor.screen.bottom = GetSystemMetrics(SM_CYSCREEN); | ||||||
|  | 			SystemParametersInfo(SPI_GETWORKAREA, 0, &(monitor.work), 0); | ||||||
|  | 			monitor.active = true; | ||||||
|  |  | ||||||
|  | 			monitors.push_back(monitor); | ||||||
|  |  | ||||||
|  | 			c_Monitors.primary = 1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		if (logging) | ||||||
|  | 		{ | ||||||
|  | 			EnumDisplayMonitors(NULL, NULL, MyInfoEnumProc, (LPARAM)NULL);  // Only logging | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (logging) | ||||||
|  | 	{ | ||||||
|  | 		DebugLog(L"------------------------------"); | ||||||
|  |  | ||||||
|  | 		std::wstring method = L"* METHOD: "; | ||||||
|  | 		if (c_Monitors.useEnumDisplayDevices) | ||||||
|  | 		{ | ||||||
|  | 			method += L"EnumDisplayDevices + "; | ||||||
|  | 			method += c_Monitors.useEnumDisplayMonitors ? L"EnumDisplayMonitors Mode" : L"EnumDisplaySettings Mode"; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			method += c_Monitors.useEnumDisplayMonitors ? L"EnumDisplayMonitors Mode" : L"Dummy Mode"; | ||||||
|  | 		} | ||||||
|  | 		DebugLog(method.c_str()); | ||||||
|  |  | ||||||
|  | 		DebugLog(L"* MONITORS: Count=%i, Primary=@%i", monitors.size(), c_Monitors.primary); | ||||||
|  | 		DebugLog(L"@0: Virtual screen"); | ||||||
|  | 		DebugLog(L"  L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", | ||||||
|  | 			c_Monitors.vsL, c_Monitors.vsT, c_Monitors.vsL + c_Monitors.vsW, c_Monitors.vsT + c_Monitors.vsH, | ||||||
|  | 			c_Monitors.vsW, c_Monitors.vsH); | ||||||
|  |  | ||||||
|  | 		for (size_t i = 0; i < monitors.size(); i++) | ||||||
|  | 		{ | ||||||
|  | 			if (monitors[i].active) | ||||||
|  | 			{ | ||||||
|  | 				DebugLog(L"@%i: %s (active), MonitorName: %s", i + 1, monitors[i].deviceName, monitors[i].monitorName); | ||||||
|  | 				DebugLog(L"  L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", | ||||||
|  | 					monitors[i].screen.left, monitors[i].screen.top, monitors[i].screen.right, monitors[i].screen.bottom, | ||||||
|  | 					monitors[i].screen.right - monitors[i].screen.left, monitors[i].screen.bottom - monitors[i].screen.top); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				DebugLog(L"@%i: %s (inactive), MonitorName: %s", i + 1, monitors[i].deviceName, monitors[i].monitorName); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		DebugLog(L"------------------------------"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* UpdateWorkareaInfo | ||||||
|  | ** | ||||||
|  | ** Updates the workarea information. | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | void CSystem::UpdateWorkareaInfo() | ||||||
|  | { | ||||||
|  | 	std::vector<MONITOR_INFO>& monitors = c_Monitors.monitors; | ||||||
|  |  | ||||||
|  | 	if (monitors.empty()) | ||||||
|  | 	{ | ||||||
|  | 		SetMultiMonitorInfo(); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for (size_t i = 0; i < monitors.size(); i++) | ||||||
|  | 	{ | ||||||
|  | 		if (monitors[i].active && monitors[i].handle != NULL) | ||||||
|  | 		{ | ||||||
|  | 			MONITORINFO info = {0}; | ||||||
|  | 			info.cbSize = sizeof(MONITORINFO); | ||||||
|  | 			GetMonitorInfo(monitors[i].handle, &info); | ||||||
|  |  | ||||||
|  | 			monitors[i].work = info.rcWork; | ||||||
|  |  | ||||||
|  | 			if (CRainmeter::GetDebug()) | ||||||
|  | 			{ | ||||||
|  | 				DebugLog(L"WorkArea @%i : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", | ||||||
|  | 					i + 1, | ||||||
|  | 					info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, | ||||||
|  | 					info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | ** GetShellDesktopWindow | ||||||
|  | ** | ||||||
|  | ** Finds the Shell's desktop window. | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | HWND CSystem::GetShellDesktopWindow() | ||||||
|  | { | ||||||
|  | 	HWND DesktopW = NULL; | ||||||
|  |  | ||||||
|  | 	HWND hwnd = FindWindow(L"Progman", L"Program Manager"); | ||||||
|  | 	if (!hwnd) return NULL;  // Default Shell (Explorer) not started | ||||||
|  |  | ||||||
|  | 	if (!(hwnd = FindWindowEx(hwnd, NULL, L"SHELLDLL_DefView", L"")) || | ||||||
|  | 		!(DesktopW = FindWindowEx(hwnd, NULL, L"SysListView32", L"FolderView")))  // for Windows 7 (with Aero) | ||||||
|  | 	{ | ||||||
|  | 		HWND WorkerW = NULL; | ||||||
|  | 		while (WorkerW = FindWindowEx(NULL, WorkerW, L"WorkerW", L"")) | ||||||
|  | 		{ | ||||||
|  | 			if ((hwnd = FindWindowEx(WorkerW, NULL, L"SHELLDLL_DefView", L"")) && | ||||||
|  | 				(DesktopW = FindWindowEx(hwnd, NULL, L"SysListView32", L"FolderView"))) break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return DesktopW; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | ** GetWorkerW | ||||||
|  | ** | ||||||
|  | ** Finds the WorkerW window. | ||||||
|  | ** If the Progman or WorkerW window is not found, this function returns NULL. | ||||||
|  | **  | ||||||
|  | ** In Windows Vista / 7 (without Aero): | ||||||
|  | ** This function returns a topmost window handle which is visible. | ||||||
|  | ** | ||||||
|  | ** In Windows 7 (with Aero): | ||||||
|  | ** This function returns a window handle which has the "SHELLDLL_DefView". | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | HWND CSystem::GetWorkerW() | ||||||
|  | { | ||||||
|  | 	HWND WorkerW = NULL; | ||||||
|  |  | ||||||
|  | 	HWND hwnd = FindWindow(L"Progman", L"Program Manager"); | ||||||
|  | 	if (!hwnd) return NULL;  // Default Shell (Explorer) not started | ||||||
|  |  | ||||||
|  | 	if ((hwnd = FindWindowEx(hwnd, NULL, L"SHELLDLL_DefView", L"")) && | ||||||
|  | 		(hwnd = FindWindowEx(hwnd, NULL, L"SysListView32", L"FolderView")))  // for Windows Vista / 7 (without Aero) | ||||||
|  | 	{ | ||||||
|  | 		while (WorkerW = FindWindowEx(NULL, WorkerW, L"WorkerW", L"")) | ||||||
|  | 		{ | ||||||
|  | 			if (IsWindowVisible(WorkerW)) | ||||||
|  | 			{ | ||||||
|  | 				// Check whether WorkerW covers whole of the screens | ||||||
|  | 				WINDOWPLACEMENT wp = {sizeof(WINDOWPLACEMENT)}; | ||||||
|  | 				GetWindowPlacement(WorkerW, &wp); | ||||||
|  |  | ||||||
|  | 				if (wp.rcNormalPosition.left == c_Monitors.vsL && | ||||||
|  | 					wp.rcNormalPosition.top == c_Monitors.vsT && | ||||||
|  | 					(wp.rcNormalPosition.right - wp.rcNormalPosition.left) == c_Monitors.vsW && | ||||||
|  | 					(wp.rcNormalPosition.bottom - wp.rcNormalPosition.top) == c_Monitors.vsH) break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else  // for Windows 7 (with Aero) | ||||||
|  | 	{ | ||||||
|  | 		while (WorkerW = FindWindowEx(NULL, WorkerW, L"WorkerW", L"")) | ||||||
|  | 		{ | ||||||
|  | 			if ((hwnd = FindWindowEx(WorkerW, NULL, L"SHELLDLL_DefView", L"")) && | ||||||
|  | 				FindWindowEx(hwnd, NULL, L"SysListView32", L"FolderView")) break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return WorkerW; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | ** MyEnumWindowsProc | ||||||
|  | ** | ||||||
|  | ** Retrieves the Rainmeter meter window pinned on desktop in Z-order. | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lParam) | ||||||
|  | { | ||||||
|  | 	bool logging = false;  // Set true if you need verbose logging. | ||||||
|  | 	WCHAR className[128] = {0}; | ||||||
|  | 	CMeterWindow* Window; | ||||||
|  |  | ||||||
|  | 	if (GetClassName(hwnd, className, 128) > 0 && | ||||||
|  | 		wcscmp(className, L"RainmeterMeterWindow") == 0 && | ||||||
|  | 		(Window = (CMeterWindow*)GetProp(hwnd, L"RAINMETER"))) | ||||||
|  | 	{ | ||||||
|  | 		if (Window->GetWindowZPosition() == ZPOSITION_ONDESKTOP) | ||||||
|  | 		{ | ||||||
|  | 			if (logging) DebugLog(L"+ [%c] 0x%08X : %s (Name: \"%s\")", IsWindowVisible(hwnd) ? L'V' : L'H', hwnd, className, Window->GetSkinName().c_str()); | ||||||
|  |  | ||||||
|  | 			if (lParam) | ||||||
|  | 			{ | ||||||
|  | 				((std::vector<CMeterWindow*>*)lParam)->push_back(Window); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			if (logging) DebugLog(L"- [%c] 0x%08X : %s (Name: \"%s\")", IsWindowVisible(hwnd) ? L'V' : L'H', hwnd, className, Window->GetSkinName().c_str()); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		if (logging) DebugLog(L"  [%c] 0x%08X : %s", IsWindowVisible(hwnd) ? L'V' : L'H', hwnd, className); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return TRUE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | ** ChangeZPosInOrder | ||||||
|  | ** | ||||||
|  | ** Arranges the meter window in Z-order. | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | void CSystem::ChangeZPosInOrder() | ||||||
|  | { | ||||||
|  | 	if (Rainmeter) | ||||||
|  | 	{ | ||||||
|  | 		bool logging = false;  // Set true if you need verbose logging. | ||||||
|  | 		std::vector<CMeterWindow*> windowsInZOrder; | ||||||
|  |  | ||||||
|  | 		if (logging) LSLog(LOG_DEBUG, L"Rainmeter", L"1: -----"); | ||||||
|  |  | ||||||
|  | 		// Retrieve the Rainmeter meter window in Z-order | ||||||
|  | 		if (logging) LSLog(LOG_DEBUG, L"Rainmeter", L" [Top-level window]"); | ||||||
|  | 		EnumWindows(MyEnumWindowsProc, (LPARAM)(&windowsInZOrder)); | ||||||
|  |  | ||||||
|  | 		HWND DesktopW = GetShellDesktopWindow(); | ||||||
|  | 		if (DesktopW) | ||||||
|  | 		{ | ||||||
|  | 			if (logging) LSLog(LOG_DEBUG, L"Rainmeter", L" [Child of Shell's desktop window]"); | ||||||
|  | 			EnumChildWindows(DesktopW, MyEnumWindowsProc, (LPARAM)(&windowsInZOrder)); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (logging) LSLog(LOG_DEBUG, L"Rainmeter", L"2: -----"); | ||||||
|  |  | ||||||
|  | 		// Reset ZPos in Z-order | ||||||
|  | 		for (size_t i = 0; i < windowsInZOrder.size(); i++) | ||||||
|  | 		{ | ||||||
|  | 			windowsInZOrder[i]->ChangeZPos(ZPOSITION_ONDESKTOP);  // reset | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (logging) | ||||||
|  | 		{ | ||||||
|  | 			LSLog(LOG_DEBUG, L"Rainmeter", L"3: -----"); | ||||||
|  | 			LSLog(LOG_DEBUG, L"Rainmeter", L" [Top-level window]"); | ||||||
|  |  | ||||||
|  | 			// Log all windows in Z-order | ||||||
|  | 			EnumWindows(MyEnumWindowsProc, (LPARAM)NULL); | ||||||
|  |  | ||||||
|  | 			if (DesktopW) | ||||||
|  | 			{ | ||||||
|  | 				LSLog(LOG_DEBUG, L"Rainmeter", L" [Child of Shell's desktop window]"); | ||||||
|  | 				EnumChildWindows(DesktopW, MyEnumWindowsProc, (LPARAM)NULL); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | ** WndProc | ||||||
|  | ** | ||||||
|  | ** The window procedure | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | LRESULT CALLBACK CSystem::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) | ||||||
|  | { | ||||||
|  | 	static int DesktopCompositionCheckCount = 0; | ||||||
|  |  | ||||||
|  | 	switch (uMsg) | ||||||
|  | 	{ | ||||||
|  | 	case WM_WINDOWPOSCHANGING: | ||||||
|  | 		((LPWINDOWPOS)lParam)->flags |= SWP_NOZORDER; | ||||||
|  | 		return 0; | ||||||
|  |  | ||||||
|  | 	case WM_TIMER: | ||||||
|  | 		switch (wParam) | ||||||
|  | 		{ | ||||||
|  | 		case TIMER_SHOWDESKTOP: | ||||||
|  | 			{ | ||||||
|  | 				HWND WorkerW = GetWorkerW(), hwnd = NULL; | ||||||
|  |  | ||||||
|  | 				if (WorkerW) | ||||||
|  | 				{ | ||||||
|  | 					hwnd = FindWindowEx(NULL, WorkerW, L"RainmeterSystemClass", L""); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if ((hwnd && !c_ShowDesktop) || (!hwnd && c_ShowDesktop)) | ||||||
|  | 				{ | ||||||
|  | 					c_ShowDesktop = !c_ShowDesktop; | ||||||
|  |  | ||||||
|  | 					if (CRainmeter::GetDebug()) | ||||||
|  | 					{ | ||||||
|  | 						DebugLog(L"System: %s", | ||||||
|  | 							c_ShowDesktop ? L"\"Show the desktop\" has been detected." : L"\"Show open windows\" has been detected."); | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					ChangeZPosInOrder(); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			return 0; | ||||||
|  |  | ||||||
|  | 		case TIMER_COMPOSITION: | ||||||
|  | 			{ | ||||||
|  | 				if (GetShellDesktopWindow() || DesktopCompositionCheckCount >= 10)  // 250ms * 10 = 2.5s | ||||||
|  | 				{ | ||||||
|  | 					KillTimer(c_Window, TIMER_COMPOSITION); | ||||||
|  |  | ||||||
|  | 					ChangeZPosInOrder(); | ||||||
|  |  | ||||||
|  | 					if (c_DwmCompositionEnabled) | ||||||
|  | 					{ | ||||||
|  | 						SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_SHOWDESKTOP, NULL); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				else | ||||||
|  | 				{ | ||||||
|  | 					DesktopCompositionCheckCount++; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  |  | ||||||
|  | 	case WM_DWMCOMPOSITIONCHANGED: | ||||||
|  | 		DebugLog(L"System: DWM desktop composition has been changed."); | ||||||
|  |  | ||||||
|  | 		KillTimer(c_Window, TIMER_SHOWDESKTOP); | ||||||
|  | 		KillTimer(c_Window, TIMER_COMPOSITION); | ||||||
|  |  | ||||||
|  | 		c_DwmCompositionEnabled = (DwmIsCompositionEnabled() == TRUE); | ||||||
|  |  | ||||||
|  | 		DesktopCompositionCheckCount = 0; | ||||||
|  | 		SetTimer(c_Window, TIMER_COMPOSITION, INTERVAL_COMPOSITION, NULL); | ||||||
|  |  | ||||||
|  | 		return 0; | ||||||
|  |  | ||||||
|  | 	case WM_DISPLAYCHANGE: | ||||||
|  | 		DebugLog(L"System: Display setting has been changed."); | ||||||
|  | 		ClearMultiMonitorInfo(); | ||||||
|  | 		CConfigParser::ClearMultiMonitorVariables(); | ||||||
|  | 	case WM_SETTINGCHANGE: | ||||||
|  | 		if (uMsg == WM_DISPLAYCHANGE || (uMsg == WM_SETTINGCHANGE && wParam == SPI_SETWORKAREA)) | ||||||
|  | 		{ | ||||||
|  | 			if (uMsg == WM_SETTINGCHANGE)  // SPI_SETWORKAREA | ||||||
|  | 			{ | ||||||
|  | 				DebugLog(L"System: Work area has been changed."); | ||||||
|  | 				UpdateWorkareaInfo(); | ||||||
|  | 				CConfigParser::UpdateWorkareaVariables(); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (Rainmeter) | ||||||
|  | 			{ | ||||||
|  | 				// Deliver WM_DISPLAYCHANGE / WM_SETTINGCHANGE message to all meter windows | ||||||
|  | 				std::map<std::wstring, CMeterWindow*>& windows = Rainmeter->GetAllMeterWindows(); | ||||||
|  | 				std::map<std::wstring, CMeterWindow*>::const_iterator iter = windows.begin(); | ||||||
|  | 				for( ; iter != windows.end(); iter++) | ||||||
|  | 				{ | ||||||
|  | 					PostMessage((*iter).second->GetWindow(), WM_DELAYED_MOVE, (WPARAM)uMsg, (LPARAM)0); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return DefWindowProc(hWnd, uMsg, wParam, lParam); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | ** DwmIsCompositionEnabled | ||||||
|  | ** | ||||||
|  | ** Returns TRUE if the DWM desktop composition is enabled. | ||||||
|  | ** | ||||||
|  | */ | ||||||
|  | BOOL CSystem::DwmIsCompositionEnabled() | ||||||
|  | { | ||||||
|  | 	BOOL fEnabled = FALSE; | ||||||
|  |  | ||||||
|  | 	typedef HRESULT (WINAPI * FPDWMISCOMPOSITIONENABLED)(BOOL* pfEnabled); | ||||||
|  | 	HINSTANCE h = LoadLibrary(L"dwmapi.dll"); | ||||||
|  | 	if (h) | ||||||
|  | 	{ | ||||||
|  | 		FPDWMISCOMPOSITIONENABLED DwmIsCompositionEnabled = (FPDWMISCOMPOSITIONENABLED)GetProcAddress(h, "DwmIsCompositionEnabled"); | ||||||
|  | 		if (DwmIsCompositionEnabled) | ||||||
|  | 		{ | ||||||
|  | 			if (DwmIsCompositionEnabled(&fEnabled) != S_OK) | ||||||
|  | 			{ | ||||||
|  | 				fEnabled = FALSE; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		FreeLibrary(h); | ||||||
|  | 	} | ||||||
|  | 	return fEnabled; | ||||||
|  | } | ||||||
							
								
								
									
										80
									
								
								Library/System.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								Library/System.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | |||||||
|  | /* | ||||||
|  |   Copyright (C) 2010 spx | ||||||
|  |  | ||||||
|  |   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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | #ifndef __RAINMETER_SYSTEM_H__ | ||||||
|  | #define __RAINMETER_SYSTEM_H__ | ||||||
|  |  | ||||||
|  | #pragma warning(disable: 4786) | ||||||
|  |  | ||||||
|  | #include <windows.h> | ||||||
|  | #include <vector> | ||||||
|  |  | ||||||
|  | struct MONITOR_INFO | ||||||
|  | { | ||||||
|  | 	bool active; | ||||||
|  | 	HMONITOR handle; | ||||||
|  | 	RECT screen; | ||||||
|  | 	RECT work; | ||||||
|  | 	WCHAR deviceName[32];					//Device name (E.g. "\\.\DISPLAY1") | ||||||
|  | 	WCHAR monitorName[128];					//Monitor name (E.g. "Generic Non-PnP Monitor") | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct MULTIMONITOR_INFO | ||||||
|  | { | ||||||
|  | 	bool useEnumDisplayDevices;				//If true, use EnumDisplayDevices function to obtain the multi-monitor information | ||||||
|  | 	bool useEnumDisplayMonitors;			//If true, use EnumDisplayMonitors function to obtain the multi-monitor information | ||||||
|  |  | ||||||
|  | 	int vsT, vsL, vsH, vsW;					//Coordinates of the top-left corner (vsT,vsL) and size (vsH,vsW) of the virtual screen | ||||||
|  | 	int primary;							//Index of the primary monitor | ||||||
|  | 	std::vector<MONITOR_INFO> monitors;		//Monitor information | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | class CSystem | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	static void Initialize(HINSTANCE instance); | ||||||
|  | 	static void Finalize(); | ||||||
|  |  | ||||||
|  | 	static const MULTIMONITOR_INFO& GetMultiMonitorInfo() { return c_Monitors; } | ||||||
|  | 	static size_t GetMonitorCount(); | ||||||
|  |  | ||||||
|  | 	static bool GetDwmCompositionEnabled() { return c_DwmCompositionEnabled; } | ||||||
|  | 	static bool GetShowDesktop() { return c_ShowDesktop; } | ||||||
|  |  | ||||||
|  | 	static HWND GetShellDesktopWindow(); | ||||||
|  | 	static HWND GetWorkerW(); | ||||||
|  |  | ||||||
|  | private: | ||||||
|  | 	static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); | ||||||
|  | 	static BOOL DwmIsCompositionEnabled(); | ||||||
|  |  | ||||||
|  | 	static void SetMultiMonitorInfo(); | ||||||
|  | 	static void ClearMultiMonitorInfo() { c_Monitors.monitors.clear(); } | ||||||
|  | 	static void UpdateWorkareaInfo(); | ||||||
|  |  | ||||||
|  | 	static void ChangeZPosInOrder(); | ||||||
|  |  | ||||||
|  | 	static HWND c_Window; | ||||||
|  |  | ||||||
|  | 	static MULTIMONITOR_INFO c_Monitors;		// Multi-Monitor info | ||||||
|  |  | ||||||
|  | 	static bool c_DwmCompositionEnabled; | ||||||
|  | 	static bool c_ShowDesktop; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -649,32 +649,6 @@ LRESULT CALLBACK CTrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA | |||||||
| 			return strlen(Buffer); | 			return strlen(Buffer); | ||||||
| 		} | 		} | ||||||
| 		return 0; | 		return 0; | ||||||
|  |  | ||||||
| 	// --- for CMeterWindow --- |  | ||||||
|  |  | ||||||
| 	case WM_DISPLAYCHANGE: |  | ||||||
| 		DebugLog(L"* Display setting has been changed."); |  | ||||||
| 		CMeterWindow::ClearMultiMonitorInfo(); |  | ||||||
| 		CConfigParser::ClearMultiMonitorVariables(); |  | ||||||
| 	case WM_SETTINGCHANGE: |  | ||||||
| 		if (uMsg == WM_DISPLAYCHANGE || (uMsg == WM_SETTINGCHANGE && wParam == SPI_SETWORKAREA)) |  | ||||||
| 		{ |  | ||||||
| 			if (uMsg == WM_SETTINGCHANGE)  // SPI_SETWORKAREA |  | ||||||
| 			{ |  | ||||||
| 				DebugLog(L"* Work area has been changed."); |  | ||||||
| 				CMeterWindow::UpdateWorkareaInfo(); |  | ||||||
| 				CConfigParser::UpdateWorkareaVariables(); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			// Deliver WM_DISPLAYCHANGE / WM_SETTINGCHANGE message to all meter windows |  | ||||||
| 			std::map<std::wstring, CMeterWindow*>& windows = Rainmeter->GetAllMeterWindows(); |  | ||||||
| 			std::map<std::wstring, CMeterWindow*>::iterator iter = windows.begin(); |  | ||||||
| 			for( ; iter != windows.end(); iter++) |  | ||||||
| 			{ |  | ||||||
| 				PostMessage((*iter).second->GetWindow(), WM_DELAYED_MOVE, (WPARAM)uMsg, (LPARAM)0); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		return 0; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return DefWindowProc(hWnd, uMsg, wParam, lParam); | 	return DefWindowProc(hWnd, uMsg, wParam, lParam); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 spx
					spx