mirror of
				https://github.com/chibicitiberiu/rainmeter-studio.git
				synced 2024-02-24 04:33:31 +00:00 
			
		
		
		
	Adding ImageCrop and MeasureName/ImageName changes by spx.
This commit is contained in:
		| @@ -950,45 +950,41 @@ Color CConfigParser::ParseColor(LPCTSTR string) | ||||
| } | ||||
|  | ||||
| /* | ||||
| ** Parse4 | ||||
| ** ParseInt4 | ||||
| ** | ||||
| ** This is a helper template that parses four comma separated values from the given string. | ||||
| ** | ||||
| */ | ||||
| template <typename T> | ||||
| bool Parse4(LPCTSTR string, T& v1, T& v2, T& v3, T& v4) | ||||
| void ParseInt4(LPCTSTR string, T& v1, T& v2, T& v3, T& v4) | ||||
| { | ||||
| 	if (wcschr(string, L',') != NULL) | ||||
| 	if (wcschr(string, L',')) | ||||
| 	{ | ||||
| 		WCHAR* parseSz = _wcsdup(string); | ||||
| 		WCHAR* token; | ||||
|  | ||||
| 		token = wcstok(parseSz, L","); | ||||
| 		if (token != NULL) | ||||
| 		if (token) | ||||
| 		{ | ||||
| 			v1 = _wtoi(token); | ||||
| 		} | ||||
| 		token = wcstok( NULL, L","); | ||||
| 		if (token != NULL) | ||||
| 		token = wcstok(NULL, L","); | ||||
| 		if (token) | ||||
| 		{ | ||||
| 			v2 = _wtoi(token); | ||||
| 		} | ||||
| 		token = wcstok( NULL, L","); | ||||
| 		if (token != NULL) | ||||
| 		token = wcstok(NULL, L","); | ||||
| 		if (token) | ||||
| 		{ | ||||
| 			v3 = _wtoi(token); | ||||
| 		} | ||||
| 		token = wcstok( NULL, L","); | ||||
| 		if (token != NULL) | ||||
| 		token = wcstok(NULL, L","); | ||||
| 		if (token) | ||||
| 		{ | ||||
| 			v4 = _wtoi(token); | ||||
| 		} | ||||
| 		free(parseSz); | ||||
|  | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| /* | ||||
| @@ -1001,7 +997,7 @@ bool Parse4(LPCTSTR string, T& v1, T& v2, T& v3, T& v4) | ||||
| Rect CConfigParser::ParseRect(LPCTSTR string) | ||||
| { | ||||
| 	Rect r; | ||||
| 	Parse4(string, r.X, r.Y, r.Width, r.Height); | ||||
| 	ParseInt4(string, r.X, r.Y, r.Width, r.Height); | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| @@ -1015,7 +1011,7 @@ Rect CConfigParser::ParseRect(LPCTSTR string) | ||||
| RECT CConfigParser::ParseRECT(LPCTSTR string) | ||||
| { | ||||
| 	RECT r = {0}; | ||||
| 	Parse4(string, r.left, r.top, r.right, r.bottom); | ||||
| 	ParseInt4(string, r.left, r.top, r.right, r.bottom); | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -557,7 +557,7 @@ void CMeter::SetAllMeasures(CMeasure* measure) | ||||
| /* | ||||
| ** SetAllMeasures | ||||
| ** | ||||
| ** Creates a vector containing all the defined measures (for Line/String) | ||||
| ** Creates a vector containing all the defined measures (for Image/Line/String) | ||||
| */ | ||||
| void CMeter::SetAllMeasures(const std::vector<CMeasure*>& measures) | ||||
| { | ||||
| @@ -571,13 +571,42 @@ void CMeter::SetAllMeasures(const std::vector<CMeasure*>& measures) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| ** ReadMeasureNames | ||||
| ** | ||||
| ** Reads measure names (MeasureName2 - MeasureName[N]) | ||||
| */ | ||||
| void CMeter::ReadMeasureNames(CConfigParser& parser, const WCHAR* section, std::vector<std::wstring>& measureNames) | ||||
| { | ||||
| 	WCHAR tmpName[64]; | ||||
|  | ||||
| 	int i = 2; | ||||
| 	bool loop = true; | ||||
| 	do  | ||||
| 	{ | ||||
| 		swprintf(tmpName, L"MeasureName%i", i); | ||||
| 		std::wstring measure = parser.ReadString(section, tmpName, L""); | ||||
| 		if (!measure.empty()) | ||||
| 		{ | ||||
| 			measureNames.push_back(measure); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			loop = false; | ||||
| 		} | ||||
| 		++i; | ||||
| 	} while(loop); | ||||
| } | ||||
|  | ||||
| /* | ||||
| ** ReplaceMeasures | ||||
| ** | ||||
| ** Replaces %1, %2 etc with the corresponding measure value | ||||
| */ | ||||
| void CMeter::ReplaceMeasures(const std::vector<std::wstring>& stringValues, std::wstring& str) | ||||
| bool CMeter::ReplaceMeasures(const std::vector<std::wstring>& stringValues, std::wstring& str) | ||||
| { | ||||
| 	bool replaced = false; | ||||
|  | ||||
| 	if (str.find(L'%') != std::wstring::npos) | ||||
| 	{ | ||||
| 		WCHAR buffer[64]; | ||||
| @@ -597,10 +626,13 @@ void CMeter::ReplaceMeasures(const std::vector<std::wstring>& stringValues, std: | ||||
| 				{ | ||||
| 					str.replace(str.begin() + pos, str.begin() + pos + wcslen(buffer), stringValues[i - 1]); | ||||
| 					start = pos + stringValues[i - 1].length(); | ||||
| 					replaced = true; | ||||
| 				} | ||||
| 			} while(pos != std::wstring::npos); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return replaced; | ||||
| } | ||||
|  | ||||
| /* | ||||
|   | ||||
| @@ -116,7 +116,8 @@ protected: | ||||
| 	void SetAllMeasures(const std::vector<CMeasure*>& measures); | ||||
| 	void ReplaceToolTipMeasures(std::wstring& str); | ||||
|  | ||||
| 	static void ReplaceMeasures(const std::vector<std::wstring>& stringValues, std::wstring& str); | ||||
| 	static void ReadMeasureNames(CConfigParser& parser, const WCHAR* section, std::vector<std::wstring>& measureNames); | ||||
| 	static bool ReplaceMeasures(const std::vector<std::wstring>& stringValues, std::wstring& str); | ||||
|  | ||||
| 	Gdiplus::Matrix m_Transformation;	// The transformation matrix | ||||
| 	std::wstring m_Name;			// Name of the meter | ||||
|   | ||||
| @@ -61,7 +61,13 @@ void CMeterImage::Initialize() | ||||
| { | ||||
| 	CMeter::Initialize(); | ||||
|  | ||||
| 	if (!m_DynamicVariables) LoadImage(true); | ||||
| 	if (!m_Measure && !m_DynamicVariables && !m_ImageName.empty()) | ||||
| 	{ | ||||
| 		m_ImageNameResult = m_Path; | ||||
| 		m_ImageNameResult += m_ImageName; | ||||
| 		m_ImageNameResult = m_MeterWindow->MakePathAbsolute(m_ImageNameResult); | ||||
| 		LoadImage(m_ImageNameResult, true); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| @@ -70,9 +76,9 @@ void CMeterImage::Initialize() | ||||
| ** Loads the image from disk | ||||
| ** | ||||
| */ | ||||
| void CMeterImage::LoadImage(bool bLoadAlways) | ||||
| void CMeterImage::LoadImage(const std::wstring& imageName, bool bLoadAlways) | ||||
| { | ||||
| 	m_Image.LoadImage(m_ImageName, bLoadAlways); | ||||
| 	m_Image.LoadImage(imageName, bLoadAlways); | ||||
|  | ||||
| 	if (m_Image.IsLoaded()) | ||||
| 	{ | ||||
| @@ -117,6 +123,12 @@ void CMeterImage::ReadConfig(const WCHAR* section) | ||||
|  | ||||
| 	CConfigParser& parser = m_MeterWindow->GetParser(); | ||||
|  | ||||
| 	// Check for extra measures | ||||
| 	if (!m_Initialized && !m_MeasureName.empty()) | ||||
| 	{ | ||||
| 		ReadMeasureNames(parser, section, m_MeasureNames); | ||||
| 	} | ||||
|  | ||||
| 	m_Path = parser.ReadString(section, L"Path", L""); | ||||
| 	if (!m_Path.empty()) | ||||
| 	{ | ||||
| @@ -127,22 +139,7 @@ void CMeterImage::ReadConfig(const WCHAR* section) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!m_Initialized || !m_Measure) | ||||
| 	{ | ||||
| 		std::wstring oldImageName = m_ImageName; | ||||
|  | ||||
| 	m_ImageName = parser.ReadString(section, L"ImageName", L""); | ||||
| 		if (!m_ImageName.empty()) | ||||
| 		{ | ||||
| 			m_ImageName.insert(0, m_Path); | ||||
| 			m_ImageName = m_MeterWindow->MakePathAbsolute(m_ImageName); | ||||
| 		} | ||||
|  | ||||
| 		if (m_DynamicVariables) | ||||
| 		{ | ||||
| 			m_NeedsReload = (oldImageName != m_ImageName); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	m_PreserveAspectRatio = 0!=parser.ReadInt(section, L"PreserveAspectRatio", 0); | ||||
| 	m_Tile = 0!=parser.ReadInt(section, L"Tile", 0); | ||||
| @@ -170,32 +167,51 @@ bool CMeterImage::Update() | ||||
| { | ||||
| 	if (CMeter::Update()) | ||||
| 	{ | ||||
| 		if (m_Measure)  //read from the measure | ||||
| 		if (m_Measure || m_DynamicVariables) | ||||
| 		{ | ||||
| 			// Store the current values so we know if the image needs to be updated | ||||
| 			std::wstring oldResult = m_ImageNameResult; | ||||
|  | ||||
| 			if (m_Measure)  // read from the measures | ||||
| 			{ | ||||
| 				std::wstring val = m_Measure->GetStringValue(false, 1, 0, false); | ||||
| 			if (!val.empty()) | ||||
|  | ||||
| 				if (m_ImageName.empty()) | ||||
| 				{ | ||||
| 				val.insert(0, m_Path); | ||||
| 				val = m_MeterWindow->MakePathAbsolute(val); | ||||
| 				if (val != m_ImageName) | ||||
| 				{ | ||||
| 					m_ImageName = val; | ||||
| 					LoadImage(true); | ||||
| 					m_ImageNameResult = val; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					LoadImage(false); | ||||
| 				} | ||||
| 			} | ||||
| 			else if (m_Image.IsLoaded()) | ||||
| 					std::vector<std::wstring> stringValues; | ||||
|  | ||||
| 					stringValues.push_back(val); | ||||
|  | ||||
| 					// Get the values for the other measures | ||||
| 					for (size_t i = 0; i < m_Measures.size(); ++i) | ||||
| 					{ | ||||
| 				m_Image.DisposeImage(); | ||||
| 						stringValues.push_back(m_Measures[i]->GetStringValue(false, 1, 0, false)); | ||||
| 					} | ||||
| 			return true; | ||||
| 		} | ||||
| 		else if (m_DynamicVariables)  //read from the skin | ||||
|  | ||||
| 					m_ImageNameResult = m_ImageName; | ||||
| 					if (!ReplaceMeasures(stringValues, m_ImageNameResult)) | ||||
| 					{ | ||||
| 			LoadImage(m_NeedsReload); | ||||
| 						// ImageName doesn't contain any measures, so use the result of MeasureName. | ||||
| 						m_ImageNameResult = val; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			else  // read from the skin | ||||
| 			{ | ||||
| 				m_ImageNameResult = m_ImageName; | ||||
| 			} | ||||
|  | ||||
| 			if (!m_ImageNameResult.empty()) | ||||
| 			{ | ||||
| 				m_ImageNameResult.insert(0, m_Path); | ||||
| 				m_ImageNameResult = m_MeterWindow->MakePathAbsolute(m_ImageNameResult); | ||||
| 			} | ||||
|  | ||||
| 			LoadImage(m_ImageNameResult, oldResult != m_ImageNameResult); | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
| @@ -278,9 +294,32 @@ bool CMeterImage::Draw(Graphics& graphics) | ||||
| */ | ||||
| void CMeterImage::BindMeasure(const std::list<CMeasure*>& measures) | ||||
| { | ||||
| 	// It's ok not to bind image meter to anything | ||||
| 	if (!m_MeasureName.empty()) | ||||
| 	{ | ||||
| 	if (m_MeasureName.empty()) return;	// Allow NULL measure binding | ||||
|  | ||||
| 	CMeter::BindMeasure(measures); | ||||
|  | ||||
| 	std::vector<std::wstring>::const_iterator j = m_MeasureNames.begin(); | ||||
| 	for (; j != m_MeasureNames.end(); ++j) | ||||
| 	{ | ||||
| 		// Go through the list and check it there is a secondary measures for us | ||||
| 		std::list<CMeasure*>::const_iterator i = measures.begin(); | ||||
| 		for( ; i != measures.end(); ++i) | ||||
| 		{ | ||||
| 			if(_wcsicmp((*i)->GetName(), (*j).c_str()) == 0) | ||||
| 			{ | ||||
| 				m_Measures.push_back(*i); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (i == measures.end()) | ||||
| 		{ | ||||
| 			std::wstring error = L"The meter [" + m_Name; | ||||
| 			error += L"] cannot be bound with ["; | ||||
| 			error += (*j); | ||||
| 			error += L"]!"; | ||||
| 			throw CError(error, __LINE__, __FILE__); | ||||
| 		} | ||||
| 	} | ||||
| 	CMeter::SetAllMeasures(m_Measures); | ||||
| } | ||||
|   | ||||
| @@ -36,10 +36,11 @@ public: | ||||
| 	virtual void BindMeasure(const std::list<CMeasure*>& measures); | ||||
|  | ||||
| protected: | ||||
| 	void LoadImage(bool bLoadAlways); | ||||
| 	void LoadImage(const std::wstring& imageName, bool bLoadAlways); | ||||
|  | ||||
| 	CTintedImage m_Image; | ||||
| 	std::wstring m_ImageName;			// Name of the image | ||||
| 	std::wstring m_ImageNameResult;		// Name of the image (as absolute path) | ||||
| 	std::wstring m_Path; | ||||
|  | ||||
| 	bool m_NeedsReload; | ||||
| @@ -47,6 +48,9 @@ protected: | ||||
| 	bool m_HeightDefined; | ||||
| 	bool m_PreserveAspectRatio;			// If true, aspect ratio of the image is preserved when the image is scaled | ||||
| 	bool m_Tile; | ||||
|  | ||||
| 	std::vector<std::wstring> m_MeasureNames; | ||||
| 	std::vector<CMeasure*> m_Measures; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -257,23 +257,7 @@ void CMeterString::ReadConfig(const WCHAR* section) | ||||
| 	// Check for extra measures | ||||
| 	if (!m_Initialized && !m_MeasureName.empty()) | ||||
| 	{ | ||||
| 		WCHAR tmpName[64]; | ||||
| 		int i = 2; | ||||
| 		bool loop = true; | ||||
| 		do  | ||||
| 		{ | ||||
| 			swprintf(tmpName, L"MeasureName%i", i); | ||||
| 			std::wstring measure = parser.ReadString(section, tmpName, L""); | ||||
| 			if (!measure.empty()) | ||||
| 			{ | ||||
| 				m_MeasureNames.push_back(measure); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				loop = false; | ||||
| 			} | ||||
| 			++i; | ||||
| 		} while(loop); | ||||
| 		ReadMeasureNames(parser, section, m_MeasureNames); | ||||
| 	} | ||||
|  | ||||
| 	m_Color = parser.ReadColor(section, L"FontColor", Color::Black); | ||||
|   | ||||
| @@ -65,9 +65,11 @@ CTintedImage::CTintedImage(bool disableTransform) : m_DisableTransform(disableTr | ||||
| 	m_Modified.dwHighDateTime = 0; | ||||
| 	m_Modified.dwLowDateTime = 0; | ||||
|  | ||||
| 	m_NeedsCrop = false; | ||||
| 	m_NeedsTinting = false; | ||||
| 	m_NeedsTransform = false; | ||||
|  | ||||
| 	m_CropMode = CROPMODE_TL; | ||||
| 	m_GreyScale = false; | ||||
| 	m_Flip = RotateNoneFlipNone; | ||||
| 	m_Rotate = 0.0f; | ||||
| @@ -166,7 +168,7 @@ void CTintedImage::LoadImage(const std::wstring& imageName, bool bLoadAlways) | ||||
| 									// Check whether the new image needs tinting (or cropping, flipping, rotating) | ||||
| 									if (!m_NeedsCrop) | ||||
| 									{ | ||||
| 										if (m_Crop.X != -1 || m_Crop.Y != -1 || m_Crop.Width != -1 || m_Crop.Height != -1) | ||||
| 										if (m_Crop.Width >= 0 || m_Crop.Height >= 0) | ||||
| 										{ | ||||
| 											m_NeedsCrop = true; | ||||
| 										} | ||||
| @@ -268,11 +270,45 @@ void CTintedImage::ApplyCrop() | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			int imageW = m_Bitmap->GetWidth(); | ||||
| 			int imageH = m_Bitmap->GetHeight(); | ||||
|  | ||||
| 			int x, y; | ||||
|  | ||||
| 			switch (m_CropMode) | ||||
| 			{ | ||||
| 			case CROPMODE_TL: | ||||
| 			default: | ||||
| 				x = m_Crop.X; | ||||
| 				y = m_Crop.Y; | ||||
| 				break; | ||||
|  | ||||
| 			case CROPMODE_TR: | ||||
| 				x = m_Crop.X + imageW; | ||||
| 				y = m_Crop.Y; | ||||
| 				break; | ||||
|  | ||||
| 			case CROPMODE_BR: | ||||
| 				x = m_Crop.X + imageW; | ||||
| 				y = m_Crop.Y + imageH; | ||||
| 				break; | ||||
|  | ||||
| 			case CROPMODE_BL: | ||||
| 				x = m_Crop.X; | ||||
| 				y = m_Crop.Y + imageH; | ||||
| 				break; | ||||
|  | ||||
| 			case CROPMODE_C: | ||||
| 				x = m_Crop.X + (imageW / 2); | ||||
| 				y = m_Crop.Y + (imageH / 2); | ||||
| 				break; | ||||
| 			} | ||||
|  | ||||
| 			Rect r(0, 0, m_Crop.Width, m_Crop.Height); | ||||
| 			m_BitmapTint = new Bitmap(r.Width, r.Height, PixelFormat32bppARGB); | ||||
|  | ||||
| 			Graphics graphics(m_BitmapTint); | ||||
| 			graphics.DrawImage(m_Bitmap, r, m_Crop.X, m_Crop.Y, r.Width, r.Height, UnitPixel); | ||||
| 			graphics.DrawImage(m_Bitmap, r, x, y, r.Width, r.Height, UnitPixel); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -444,6 +480,7 @@ void CTintedImage::ReadConfig(CConfigParser& parser, const WCHAR* section) | ||||
| { | ||||
| 	// Store the current values so we know if the image needs to be tinted or transformed | ||||
| 	Rect oldCrop = m_Crop; | ||||
| 	CROPMODE oldCropMode = m_CropMode; | ||||
| 	bool oldGreyScale = m_GreyScale; | ||||
| 	ColorMatrix oldColorMatrix = m_ColorMatrix; | ||||
| 	RotateFlipType oldFlip = m_Flip; | ||||
| @@ -451,10 +488,58 @@ void CTintedImage::ReadConfig(CConfigParser& parser, const WCHAR* section) | ||||
|  | ||||
| 	if (!m_DisableTransform) | ||||
| 	{ | ||||
| 		m_Crop = parser.ReadRect(section, m_ConfigImageCrop.c_str(), Rect(-1,-1,-1,-1)); | ||||
| 		m_Crop.X = m_Crop.Y = m_Crop.Width = m_Crop.Height = -1; | ||||
| 		m_CropMode = CROPMODE_TL; | ||||
|  | ||||
| 		std::wstring crop = parser.ReadString(section, m_ConfigImageCrop.c_str(), L""); | ||||
| 		if (!crop.empty()) | ||||
| 		{ | ||||
| 			if (wcschr(crop.c_str(), L',')) | ||||
| 			{ | ||||
| 				WCHAR* parseSz = _wcsdup(crop.c_str()); | ||||
| 				WCHAR* token; | ||||
| 				 | ||||
| 				token = wcstok(parseSz, L","); | ||||
| 				if (token) | ||||
| 				{ | ||||
| 					m_Crop.X = _wtoi(token); | ||||
| 				} | ||||
| 				token = wcstok(NULL, L","); | ||||
| 				if (token) | ||||
| 				{ | ||||
| 					m_Crop.Y = _wtoi(token); | ||||
| 				} | ||||
| 				token = wcstok(NULL, L","); | ||||
| 				if (token) | ||||
| 				{ | ||||
| 					m_Crop.Width = _wtoi(token); | ||||
| 				} | ||||
| 				token = wcstok(NULL, L","); | ||||
| 				if (token) | ||||
| 				{ | ||||
| 					m_Crop.Height = _wtoi(token); | ||||
| 				} | ||||
| 				token = wcstok(NULL, L","); | ||||
| 				if (token) | ||||
| 				{ | ||||
| 					m_CropMode = (CROPMODE)_wtoi(token); | ||||
| 				} | ||||
| 				free(parseSz); | ||||
| 			} | ||||
|  | ||||
| 	m_NeedsCrop = (oldCrop.X != m_Crop.X || oldCrop.Y != m_Crop.Y || oldCrop.Width != m_Crop.Width || oldCrop.Height != m_Crop.Height); | ||||
| 			if (m_CropMode < CROPMODE_TL || m_CropMode > CROPMODE_C) | ||||
| 			{ | ||||
| 				std::wstring error = m_ConfigImageCrop + L"="; | ||||
| 				error += crop; | ||||
| 				error += L" (origin) is not valid in meter ["; | ||||
| 				error += section; | ||||
| 				error += L"]."; | ||||
| 				throw CError(error, __LINE__, __FILE__); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	m_NeedsCrop = (oldCrop.X != m_Crop.X || oldCrop.Y != m_Crop.Y || oldCrop.Width != m_Crop.Width || oldCrop.Height != m_Crop.Height || oldCropMode != m_CropMode); | ||||
|  | ||||
| 	m_GreyScale = 0!=parser.ReadInt(section, m_ConfigGreyscale.c_str(), 0); | ||||
|  | ||||
|   | ||||
| @@ -22,6 +22,15 @@ | ||||
| #include "Meter.h" | ||||
| #include "MeterWindow.h" | ||||
|  | ||||
| enum CROPMODE | ||||
| { | ||||
| 	CROPMODE_TL = 1, | ||||
| 	CROPMODE_TR, | ||||
| 	CROPMODE_BR, | ||||
| 	CROPMODE_BL, | ||||
| 	CROPMODE_C | ||||
| }; | ||||
|  | ||||
| class CTintedImage | ||||
| { | ||||
| public: | ||||
| @@ -77,6 +86,7 @@ protected: | ||||
| 	bool m_NeedsTransform; | ||||
|  | ||||
| 	Gdiplus::Rect m_Crop; | ||||
| 	CROPMODE m_CropMode; | ||||
| 	bool m_GreyScale; | ||||
| 	Gdiplus::ColorMatrix m_ColorMatrix; | ||||
| 	Gdiplus::RotateFlipType m_Flip; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Birunthan Mohanathas
					Birunthan Mohanathas