mirror of
				https://github.com/chibicitiberiu/rainmeter-studio.git
				synced 2024-02-24 04:33:31 +00:00 
			
		
		
		
	- Added BackgroundMode=4 for tiling background image.
- Added tinting functions for Background. - Added "ImageCrop" option to Meter=IMAGE/BAR/HISTOGRAM/ROTATOR and Background. - Added "Tile" option to Meter=IMAGE. - Some code cleanups.
This commit is contained in:
		| @@ -672,6 +672,12 @@ const std::wstring& CConfigParser::ReadString(LPCTSTR section, LPCTSTR key, LPCT | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| bool CConfigParser::IsValueDefined(LPCTSTR section, LPCTSTR key) | ||||
| { | ||||
| 	ReadString(section, key, L"", false); | ||||
| 	return !m_LastDefaultUsed; | ||||
| } | ||||
|  | ||||
| void CConfigParser::AddMeasure(CMeasure* pMeasure) | ||||
| { | ||||
| 	if (pMeasure) | ||||
| @@ -775,6 +781,20 @@ Color CConfigParser::ReadColor(LPCTSTR section, LPCTSTR key, const Color& defVal | ||||
| 	return (m_LastDefaultUsed) ? defValue : ParseColor(result.c_str()); | ||||
| } | ||||
|  | ||||
| Rect CConfigParser::ReadRect(LPCTSTR section, LPCTSTR key, const Rect& defValue) | ||||
| { | ||||
| 	const std::wstring& result = ReadString(section, key, L""); | ||||
|  | ||||
| 	return (m_LastDefaultUsed) ? defValue : ParseRect(result.c_str()); | ||||
| } | ||||
|  | ||||
| RECT CConfigParser::ReadRECT(LPCTSTR section, LPCTSTR key, const RECT& defValue) | ||||
| { | ||||
| 	const std::wstring& result = ReadString(section, key, L""); | ||||
|  | ||||
| 	return (m_LastDefaultUsed) ? defValue : ParseRECT(result.c_str()); | ||||
| } | ||||
|  | ||||
| /* | ||||
| ** Tokenize | ||||
| ** | ||||
| @@ -929,6 +949,76 @@ Color CConfigParser::ParseColor(LPCTSTR string) | ||||
| 	return Color(A, R, G, B); | ||||
| } | ||||
|  | ||||
| /* | ||||
| ** Parse4 | ||||
| ** | ||||
| ** 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) | ||||
| { | ||||
| 	if (wcschr(string, L',') != NULL) | ||||
| 	{ | ||||
| 		WCHAR* parseSz = _wcsdup(string); | ||||
| 		WCHAR* token; | ||||
|  | ||||
| 		token = wcstok(parseSz, L","); | ||||
| 		if (token != NULL) | ||||
| 		{ | ||||
| 			v1 = _wtoi(token); | ||||
| 		} | ||||
| 		token = wcstok( NULL, L","); | ||||
| 		if (token != NULL) | ||||
| 		{ | ||||
| 			v2 = _wtoi(token); | ||||
| 		} | ||||
| 		token = wcstok( NULL, L","); | ||||
| 		if (token != NULL) | ||||
| 		{ | ||||
| 			v3 = _wtoi(token); | ||||
| 		} | ||||
| 		token = wcstok( NULL, L","); | ||||
| 		if (token != NULL) | ||||
| 		{ | ||||
| 			v4 = _wtoi(token); | ||||
| 		} | ||||
| 		free(parseSz); | ||||
|  | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| /* | ||||
| ** ParseRect | ||||
| ** | ||||
| ** This is a helper method that parses the Gdiplus::Rect values from the given string. | ||||
| ** The rect can be supplied as four comma separated values (X/Y/Width/Height). | ||||
| ** | ||||
| */ | ||||
| Rect CConfigParser::ParseRect(LPCTSTR string) | ||||
| { | ||||
| 	Rect r; | ||||
| 	Parse4(string, r.X, r.Y, r.Width, r.Height); | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| /* | ||||
| ** ParseRECT | ||||
| ** | ||||
| ** This is a helper method that parses the RECT values from the given string. | ||||
| ** The rect can be supplied as four comma separated values (left/top/right/bottom). | ||||
| ** | ||||
| */ | ||||
| RECT CConfigParser::ParseRECT(LPCTSTR string) | ||||
| { | ||||
| 	RECT r = {0}; | ||||
| 	Parse4(string, r.left, r.top, r.right, r.bottom); | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| //============================================================================== | ||||
| /** | ||||
| ** Reads the given ini file and fills the m_Values and m_Keys maps. | ||||
|   | ||||
| @@ -52,10 +52,13 @@ public: | ||||
| 	void ResetMonitorVariables(CMeterWindow* meterWindow = NULL); | ||||
|  | ||||
| 	const std::wstring& ReadString(LPCTSTR section, LPCTSTR key, LPCTSTR defValue, bool bReplaceMeasures = true); | ||||
| 	bool IsValueDefined(LPCTSTR section, LPCTSTR key); | ||||
| 	double ReadFloat(LPCTSTR section, LPCTSTR key, double defValue); | ||||
| 	double ReadFormula(LPCTSTR section, LPCTSTR key, double defValue); | ||||
| 	int ReadInt(LPCTSTR section, LPCTSTR key, int defValue); | ||||
| 	Gdiplus::Color ReadColor(LPCTSTR section, LPCTSTR key, const Gdiplus::Color& defValue); | ||||
| 	Gdiplus::Rect ReadRect(LPCTSTR section, LPCTSTR key, const Gdiplus::Rect& defValue); | ||||
| 	RECT ReadRECT(LPCTSTR section, LPCTSTR key, const RECT& defValue); | ||||
| 	std::vector<Gdiplus::REAL> ReadFloats(LPCTSTR section, LPCTSTR key); | ||||
|  | ||||
| 	const std::wstring& GetFilename() { return m_Filename; } | ||||
| @@ -67,6 +70,8 @@ public: | ||||
| 	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 Gdiplus::Rect ParseRect(LPCTSTR string); | ||||
| 	static RECT ParseRECT(LPCTSTR string); | ||||
|  | ||||
| 	static void ClearMultiMonitorVariables() { c_MonitorVariables.clear(); } | ||||
| 	static void UpdateWorkareaVariables() { SetMultiMonitorVariables(false); } | ||||
|   | ||||
| @@ -375,6 +375,11 @@ void CMeter::ReadConfig(const WCHAR* section) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!m_Initialized) | ||||
| 	{ | ||||
| 		m_MeasureName = parser.ReadString(section, L"MeasureName", L""); | ||||
| 	} | ||||
|  | ||||
| 	m_SolidBevel = (BEVELTYPE)parser.ReadInt(section, L"BevelType", BEVELTYPE_NONE); | ||||
|  | ||||
| 	m_SolidColor = parser.ReadColor(section, L"SolidColor", Color(0, 0, 0, 0)); | ||||
| @@ -407,8 +412,6 @@ void CMeter::ReadConfig(const WCHAR* section) | ||||
| 	m_ToolTipType = 0!=parser.ReadInt(section, L"ToolTipType", 0); | ||||
| 	m_ToolTipHidden = 0!=parser.ReadInt(section, L"ToolTipHidden", m_ToolTipHidden); | ||||
|  | ||||
| 	m_MeasureName = parser.ReadString(section, L"MeasureName", L""); | ||||
|  | ||||
| 	UINT updateDivider = parser.ReadInt(section, L"UpdateDivider", 1); | ||||
| 	if (updateDivider != m_UpdateDivider) | ||||
| 	{ | ||||
| @@ -574,6 +577,8 @@ void CMeter::SetAllMeasures(const std::vector<CMeasure*>& measures) | ||||
| ** Replaces %1, %2 etc with the corresponding measure value | ||||
| */ | ||||
| void CMeter::ReplaceMeasures(const std::vector<std::wstring>& stringValues, std::wstring& str) | ||||
| { | ||||
| 	if (str.find(L'%') != std::wstring::npos) | ||||
| 	{ | ||||
| 		WCHAR buffer[64]; | ||||
|  | ||||
| @@ -596,6 +601,7 @@ void CMeter::ReplaceMeasures(const std::vector<std::wstring>& stringValues, std: | ||||
| 			} while(pos != std::wstring::npos); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| ** ReplaceToolTipMeasures | ||||
|   | ||||
| @@ -210,11 +210,14 @@ void CMeterHistogram::ReadConfig(const WCHAR* section) | ||||
| 	m_SecondaryColor = parser.ReadColor(section, L"SecondaryColor", Color::Red); | ||||
| 	m_BothColor = parser.ReadColor(section, L"BothColor", Color::Yellow); | ||||
|  | ||||
| 	if (!m_Initialized && !m_MeasureName.empty()) | ||||
| 	{ | ||||
| 		m_SecondaryMeasureName = parser.ReadString(section, L"MeasureName2", L""); | ||||
| 		if (m_SecondaryMeasureName.empty()) | ||||
| 		{ | ||||
| 			m_SecondaryMeasureName = parser.ReadString(section, L"SecondaryMeasureName", L""); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	m_PrimaryImageName = parser.ReadString(section, L"PrimaryImage", L""); | ||||
| 	if (!m_PrimaryImageName.empty()) | ||||
|   | ||||
| @@ -38,6 +38,7 @@ CMeterImage::CMeterImage(CMeterWindow* meterWindow) : CMeter(meterWindow) | ||||
| 	m_WidthDefined = false; | ||||
| 	m_HeightDefined = false; | ||||
| 	m_PreserveAspectRatio = false; | ||||
| 	m_Tile = false; | ||||
| } | ||||
|  | ||||
| /* | ||||
| @@ -85,14 +86,14 @@ void CMeterImage::LoadImage(bool bLoadAlways) | ||||
| 		{ | ||||
| 			if (!m_HeightDefined) | ||||
| 			{ | ||||
| 				m_H = (imageW == 0) ? 0 : (int)(m_W * imageH / (double)imageW); | ||||
| 				m_H = (imageW == 0) ? 0 : (m_Tile) ? imageH : (int)(m_W * imageH / (double)imageW); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			if (m_HeightDefined) | ||||
| 			{ | ||||
| 				m_W = (imageH == 0) ? 0 : (int)(m_H * imageW / (double)imageH); | ||||
| 				m_W = (imageH == 0) ? 0 : (m_Tile) ? imageW : (int)(m_H * imageW / (double)imageH); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| @@ -144,12 +145,13 @@ void CMeterImage::ReadConfig(const WCHAR* section) | ||||
| 	} | ||||
|  | ||||
| 	m_PreserveAspectRatio = 0!=parser.ReadInt(section, L"PreserveAspectRatio", 0); | ||||
| 	m_Tile = 0!=parser.ReadInt(section, L"Tile", 0); | ||||
|  | ||||
| 	if (-1 != (int)parser.ReadFormula(section, L"W", -1)) | ||||
| 	if (parser.IsValueDefined(section, L"W")) | ||||
| 	{ | ||||
| 		m_WidthDefined = true; | ||||
| 	} | ||||
| 	if (-1 != (int)parser.ReadFormula(section, L"H", -1)) | ||||
| 	if (parser.IsValueDefined(section, L"H")) | ||||
| 	{ | ||||
| 		m_HeightDefined = true; | ||||
| 	} | ||||
| @@ -215,17 +217,32 @@ bool CMeterImage::Draw(Graphics& graphics) | ||||
| 		// Copy the image over the doublebuffer | ||||
| 		Bitmap* drawBitmap = m_Image.GetImage(); | ||||
|  | ||||
| 		int x = GetX(); | ||||
| 		int y = GetY(); | ||||
| 		int imageW = drawBitmap->GetWidth(); | ||||
| 		int imageH = drawBitmap->GetHeight(); | ||||
|  | ||||
| 		int drawW, drawH; | ||||
|  | ||||
| 		if (m_PreserveAspectRatio) | ||||
| 		{ | ||||
| 		if (imageW == 0 || imageH == 0 || m_W == 0 || m_H == 0) return true; | ||||
|  | ||||
| 		int x = GetX(); | ||||
| 		int y = GetY(); | ||||
|  | ||||
| 		int drawW = m_W; | ||||
| 		int drawH = m_H; | ||||
|  | ||||
| 		ImageAttributes imgAttr; | ||||
| 		bool useImgAttr = false; | ||||
|  | ||||
| 		if (m_Tile) | ||||
| 		{ | ||||
| 			imageW = m_W; | ||||
| 			imageH = m_H; | ||||
|  | ||||
| 			imgAttr.SetWrapMode(WrapModeTile); | ||||
| 			useImgAttr = true; | ||||
| 		} | ||||
| 		else if (m_PreserveAspectRatio) | ||||
| 		{ | ||||
| 			if (m_WidthDefined && m_HeightDefined) | ||||
| 			{ | ||||
| 				REAL imageRatio = imageW / (REAL)imageH; | ||||
| 				REAL meterRatio = m_W / (REAL)m_H; | ||||
|  | ||||
| @@ -244,14 +261,10 @@ bool CMeterImage::Draw(Graphics& graphics) | ||||
| 				x += (m_W - drawW) / 2; | ||||
| 				y += (m_H - drawH) / 2; | ||||
| 			} | ||||
| 		else | ||||
| 		{ | ||||
| 			drawW = m_W; | ||||
| 			drawH = m_H; | ||||
| 		} | ||||
|  | ||||
| 		Rect r(x, y, drawW, drawH); | ||||
| 		graphics.DrawImage(drawBitmap, r, 0, 0, imageW, imageH, UnitPixel); | ||||
| 		graphics.DrawImage(drawBitmap, r, 0, 0, imageW, imageH, UnitPixel, (useImgAttr) ? &imgAttr : NULL); | ||||
| 	} | ||||
|  | ||||
| 	return true; | ||||
|   | ||||
| @@ -46,6 +46,7 @@ protected: | ||||
| 	bool m_WidthDefined; | ||||
| 	bool m_HeightDefined; | ||||
| 	bool m_PreserveAspectRatio;			// If true, aspect ratio of the image is preserved when the image is scaled | ||||
| 	bool m_Tile; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -109,7 +109,6 @@ void CMeterLine::ReadConfig(const WCHAR* section) | ||||
|  | ||||
| 	m_Colors.clear(); | ||||
| 	m_ScaleValues.clear(); | ||||
| 	m_MeasureNames.clear(); | ||||
|  | ||||
| 	for (int i = 0; i < lineCount; ++i) | ||||
| 	{ | ||||
| @@ -135,12 +134,15 @@ void CMeterLine::ReadConfig(const WCHAR* section) | ||||
|  | ||||
| 		m_ScaleValues.push_back(parser.ReadFloat(section, tmpName, 1.0)); | ||||
|  | ||||
| 		if (!m_Initialized && !m_MeasureName.empty()) | ||||
| 		{ | ||||
| 			if (i != 0) | ||||
| 			{ | ||||
| 				swprintf(tmpName, L"MeasureName%i", i + 1); | ||||
| 				m_MeasureNames.push_back(parser.ReadString(section, tmpName, L"")); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	m_Flip = 0!=parser.ReadInt(section, L"Flip", 0); | ||||
| 	m_Autoscale = 0!=parser.ReadInt(section, L"AutoScale", 0); | ||||
|   | ||||
| @@ -244,8 +244,6 @@ void CMeterString::Initialize() | ||||
| */ | ||||
| void CMeterString::ReadConfig(const WCHAR* section) | ||||
| { | ||||
| 	WCHAR tmpName[64]; | ||||
|  | ||||
| 	// Store the current font values so we know if the font needs to be updated | ||||
| 	std::wstring oldFontFace = m_FontFace; | ||||
| 	int oldFontSize = m_FontSize; | ||||
| @@ -256,11 +254,10 @@ void CMeterString::ReadConfig(const WCHAR* section) | ||||
|  | ||||
| 	CConfigParser& parser = m_MeterWindow->GetParser(); | ||||
|  | ||||
| 	m_MeasureNames.clear(); | ||||
|  | ||||
| 	// Check for extra measures | ||||
| 	if (!m_MeasureName.empty()) | ||||
| 	if (!m_Initialized && !m_MeasureName.empty()) | ||||
| 	{ | ||||
| 		WCHAR tmpName[64]; | ||||
| 		int i = 2; | ||||
| 		bool loop = true; | ||||
| 		do  | ||||
| @@ -415,7 +412,7 @@ void CMeterString::ReadConfig(const WCHAR* section) | ||||
| 		throw CError(error, __LINE__, __FILE__); | ||||
| 	} | ||||
|  | ||||
| 	if (-1 != (int)parser.ReadFormula(section, L"W", -1) && -1 != (int)parser.ReadFormula(section, L"H", -1)) | ||||
| 	if (parser.IsValueDefined(section, L"W") && parser.IsValueDefined(section, L"H")) | ||||
| 	{ | ||||
| 		m_DimensionsDefined = true; | ||||
| 	} | ||||
|   | ||||
| @@ -30,6 +30,7 @@ | ||||
| #include "MeasureNet.h" | ||||
| #include "MeasurePlugin.h" | ||||
| #include "MeterButton.h" | ||||
| #include "TintedImage.h" | ||||
|  | ||||
| using namespace Gdiplus; | ||||
|  | ||||
| @@ -1735,21 +1736,13 @@ bool CMeterWindow::ReadSkin() | ||||
| 	m_BackgroundName = m_Parser.ReadString(L"Rainmeter", L"Background", L""); | ||||
| 	m_BackgroundName = MakePathAbsolute(m_BackgroundName); | ||||
|  | ||||
| 	std::wstring margins = m_Parser.ReadString(L"Rainmeter", L"BackgroundMargins", L"0, 0, 0, 0"); | ||||
| 	int left = 0, top = 0, right = 0, bottom = 0; | ||||
| 	swscanf(margins.c_str(), L"%i, %i, %i, %i", &left, &top, &right, &bottom); | ||||
| 	m_BackgroundMargins.X = left; | ||||
| 	m_BackgroundMargins.Width = right - left; | ||||
| 	m_BackgroundMargins.Y = top; | ||||
| 	m_BackgroundMargins.Height = bottom - top; | ||||
| 	m_BackgroundMargins = m_Parser.ReadRect(L"Rainmeter", L"BackgroundMargins", Rect(0,0,0,0)); | ||||
| 	m_BackgroundMargins.Width -= m_BackgroundMargins.X; | ||||
| 	m_BackgroundMargins.Height -= m_BackgroundMargins.Y; | ||||
|  | ||||
| 	margins = m_Parser.ReadString(L"Rainmeter", L"DragMargins", L"0, 0, 0, 0"); | ||||
| 	left = 0, top = 0, right = 0, bottom = 0; | ||||
| 	swscanf(margins.c_str(), L"%i, %i, %i, %i", &left, &top, &right, &bottom); | ||||
| 	m_DragMargins.X = left; | ||||
| 	m_DragMargins.Width = right - left; | ||||
| 	m_DragMargins.Y = top; | ||||
| 	m_DragMargins.Height = bottom - top; | ||||
| 	m_DragMargins = m_Parser.ReadRect(L"Rainmeter", L"DragMargins", Rect(0,0,0,0)); | ||||
| 	m_DragMargins.Width -= m_DragMargins.X; | ||||
| 	m_DragMargins.Height -= m_DragMargins.Y; | ||||
|  | ||||
| 	m_BackgroundMode = (BGMODE)m_Parser.ReadInt(L"Rainmeter", L"BackgroundMode", BGMODE_IMAGE); | ||||
| 	m_SolidBevel = (BEVELTYPE)m_Parser.ReadInt(L"Rainmeter", L"BevelType", BEVELTYPE_NONE); | ||||
| @@ -1760,7 +1753,7 @@ bool CMeterWindow::ReadSkin() | ||||
|  | ||||
| 	m_DynamicWindowSize = 0!=m_Parser.ReadInt(L"Rainmeter", L"DynamicWindowSize", 0); | ||||
|  | ||||
| 	if ((m_BackgroundMode == BGMODE_IMAGE || m_BackgroundMode == BGMODE_SCALED_IMAGE) && m_BackgroundName.empty()) | ||||
| 	if ((m_BackgroundMode == BGMODE_IMAGE || m_BackgroundMode == BGMODE_SCALED_IMAGE || m_BackgroundMode == BGMODE_TILED_IMAGE) && m_BackgroundName.empty()) | ||||
| 	{ | ||||
| 		m_BackgroundMode = BGMODE_COPY; | ||||
| 	} | ||||
| @@ -2106,17 +2099,16 @@ bool CMeterWindow::ResizeWindow(bool reset) | ||||
| 		m_Background = NULL; | ||||
| 	} | ||||
|  | ||||
| 	if ((m_BackgroundMode == BGMODE_IMAGE || m_BackgroundMode == BGMODE_SCALED_IMAGE) && !m_BackgroundName.empty()) | ||||
| 	if ((m_BackgroundMode == BGMODE_IMAGE || m_BackgroundMode == BGMODE_SCALED_IMAGE || m_BackgroundMode == BGMODE_TILED_IMAGE) && !m_BackgroundName.empty()) | ||||
| 	{ | ||||
| 		// Load the background | ||||
| 		m_Background = new Bitmap(m_BackgroundName.c_str()); | ||||
| 		Status status = m_Background->GetLastStatus(); | ||||
| 		if(Ok != status) | ||||
| 		CTintedImage tintedBackground; | ||||
| 		tintedBackground.SetConfigAttributes(L"Background", NULL); | ||||
| 		tintedBackground.ReadConfig(m_Parser, L"Rainmeter"); | ||||
| 		tintedBackground.LoadImage(m_BackgroundName, true); | ||||
|  | ||||
| 		if (!tintedBackground.IsLoaded()) | ||||
| 		{ | ||||
| 			std::wstring err = L"Unable to load background: " + m_BackgroundName; | ||||
| 			MessageBox(m_Window, err.c_str(), APPNAME, MB_OK | MB_TOPMOST | MB_ICONEXCLAMATION); | ||||
| 			delete m_Background; | ||||
| 			m_Background = NULL; | ||||
| 			m_BackgroundSize.cx = 0; | ||||
| 			m_BackgroundSize.cy = 0; | ||||
|  | ||||
| @@ -2125,81 +2117,99 @@ bool CMeterWindow::ResizeWindow(bool reset) | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			// Calculate the window dimensions | ||||
| 			m_BackgroundSize.cx = m_Background->GetWidth(); | ||||
| 			m_BackgroundSize.cy = m_Background->GetHeight(); | ||||
| 			Bitmap* tempBackground = tintedBackground.GetImage(); | ||||
|  | ||||
| 			// Calculate the window dimensions | ||||
| 			m_BackgroundSize.cx = tempBackground->GetWidth(); | ||||
| 			m_BackgroundSize.cy = tempBackground->GetHeight(); | ||||
|  | ||||
| 			if (m_BackgroundMode == BGMODE_IMAGE) | ||||
| 			{ | ||||
| 				m_Background = tempBackground->Clone(0, 0, m_BackgroundSize.cx, m_BackgroundSize.cy, PixelFormat32bppARGB); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				w = max(w, m_BackgroundSize.cx); | ||||
| 				h = max(h, m_BackgroundSize.cy); | ||||
|  | ||||
| 				// Scale the background to fill the whole window | ||||
| 				Bitmap* background = new Bitmap(w, h, PixelFormat32bppARGB); | ||||
|  | ||||
| 				Graphics graphics(background); | ||||
|  | ||||
| 				if (m_BackgroundMode == BGMODE_SCALED_IMAGE) | ||||
| 				{ | ||||
| 				// Scale the background to fill the whole window | ||||
| 				Bitmap* scaledBackground = new Bitmap(w, h, PixelFormat32bppARGB); | ||||
| 					RECT m = {m_BackgroundMargins.GetLeft(), m_BackgroundMargins.GetTop(), m_BackgroundMargins.GetRight(), m_BackgroundMargins.GetBottom()}; | ||||
|  | ||||
| 				Graphics graphics(scaledBackground); | ||||
|  | ||||
| 				if (m_BackgroundMargins.GetTop() > 0)  | ||||
| 					if (m.top > 0)  | ||||
| 					{ | ||||
| 					if (m_BackgroundMargins.GetLeft() > 0)  | ||||
| 						if (m.left > 0)  | ||||
| 						{ | ||||
| 							// Top-Left | ||||
| 						Rect r(0, 0, m_BackgroundMargins.GetLeft(), m_BackgroundMargins.GetTop()); | ||||
| 						graphics.DrawImage(m_Background, r, 0, 0, m_BackgroundMargins.GetLeft(), m_BackgroundMargins.GetTop(), UnitPixel); | ||||
| 							Rect r(0, 0, m.left, m.top); | ||||
| 							graphics.DrawImage(tempBackground, r, 0, 0, m.left, m.top, UnitPixel); | ||||
| 						} | ||||
|  | ||||
| 						// Top | ||||
| 					Rect r(m_BackgroundMargins.GetLeft(), 0, w - m_BackgroundMargins.GetLeft() - m_BackgroundMargins.GetRight(), m_BackgroundMargins.GetTop()); | ||||
| 					graphics.DrawImage(m_Background, r, m_BackgroundMargins.GetLeft(), 0, m_Background->GetWidth() - m_BackgroundMargins.GetLeft() - m_BackgroundMargins.GetRight(), m_BackgroundMargins.GetTop(), UnitPixel); | ||||
| 						Rect r(m.left, 0, w - m.left - m.right, m.top); | ||||
| 						graphics.DrawImage(tempBackground, r, m.left, 0, m_BackgroundSize.cx - m.left - m.right, m.top, UnitPixel); | ||||
|  | ||||
| 					if (m_BackgroundMargins.GetRight() > 0)  | ||||
| 						if (m.right > 0)  | ||||
| 						{ | ||||
| 							// Top-Right | ||||
| 						Rect r(w - m_BackgroundMargins.GetRight(), 0, m_BackgroundMargins.GetRight(), m_BackgroundMargins.GetTop()); | ||||
| 						graphics.DrawImage(m_Background, r, m_Background->GetWidth() - m_BackgroundMargins.GetRight(), 0, m_BackgroundMargins.GetRight(), m_BackgroundMargins.GetTop(), UnitPixel); | ||||
| 							Rect r(w - m.right, 0, m.right, m.top); | ||||
| 							graphics.DrawImage(tempBackground, r, m_BackgroundSize.cx - m.right, 0, m.right, m.top, UnitPixel); | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 				if (m_BackgroundMargins.GetLeft() > 0)  | ||||
| 					if (m.left > 0)  | ||||
| 					{ | ||||
| 						// Left | ||||
| 					Rect r(0, m_BackgroundMargins.GetTop(), m_BackgroundMargins.GetLeft(), h - m_BackgroundMargins.GetTop() - m_BackgroundMargins.GetBottom()); | ||||
| 					graphics.DrawImage(m_Background, r, 0, m_BackgroundMargins.GetTop(), m_BackgroundMargins.GetLeft(), m_Background->GetHeight() - m_BackgroundMargins.GetTop() - m_BackgroundMargins.GetBottom(), UnitPixel); | ||||
| 						Rect r(0, m.top, m.left, h - m.top - m.bottom); | ||||
| 						graphics.DrawImage(tempBackground, r, 0, m.top, m.left, m_BackgroundSize.cy - m.top - m.bottom, UnitPixel); | ||||
| 					} | ||||
|  | ||||
| 					// Center | ||||
| 				Rect r(m_BackgroundMargins.GetLeft(), m_BackgroundMargins.GetTop(), w - m_BackgroundMargins.GetLeft() - m_BackgroundMargins.GetRight(), h - m_BackgroundMargins.GetTop() - m_BackgroundMargins.GetBottom()); | ||||
| 				graphics.DrawImage(m_Background, r, m_BackgroundMargins.GetLeft(), m_BackgroundMargins.GetTop(), m_Background->GetWidth() - m_BackgroundMargins.GetLeft() - m_BackgroundMargins.GetRight(), m_Background->GetHeight() - m_BackgroundMargins.GetTop() - m_BackgroundMargins.GetBottom(), UnitPixel); | ||||
| 					Rect r(m.left, m.top, w - m.left - m.right, h - m.top - m.bottom); | ||||
| 					graphics.DrawImage(tempBackground, r, m.left, m.top, m_BackgroundSize.cx - m.left - m.right, m_BackgroundSize.cy - m.top - m.bottom, UnitPixel); | ||||
|  | ||||
| 				if (m_BackgroundMargins.GetRight() > 0)  | ||||
| 					if (m.right > 0)  | ||||
| 					{ | ||||
| 						// Right | ||||
| 					Rect r(w - m_BackgroundMargins.GetRight(), m_BackgroundMargins.GetTop(), m_BackgroundMargins.GetRight(), h - m_BackgroundMargins.GetTop() - m_BackgroundMargins.GetBottom()); | ||||
| 					graphics.DrawImage(m_Background, r, m_Background->GetWidth() - m_BackgroundMargins.GetRight(), m_BackgroundMargins.GetTop(), m_BackgroundMargins.GetRight(), m_Background->GetHeight() - m_BackgroundMargins.GetTop() - m_BackgroundMargins.GetBottom(), UnitPixel); | ||||
| 						Rect r(w - m.right, m.top, m.right, h - m.top - m.bottom); | ||||
| 						graphics.DrawImage(tempBackground, r, m_BackgroundSize.cx - m.right, m.top, m.right, m_BackgroundSize.cy - m.top - m.bottom, UnitPixel); | ||||
| 					} | ||||
| 					 | ||||
| 				if (m_BackgroundMargins.GetBottom() > 0)  | ||||
| 					if (m.bottom > 0)  | ||||
| 					{ | ||||
| 					if (m_BackgroundMargins.GetLeft() > 0)  | ||||
| 						if (m.left > 0)  | ||||
| 						{ | ||||
| 							// Bottom-Left | ||||
| 						Rect r(0, h - m_BackgroundMargins.GetBottom(), m_BackgroundMargins.GetLeft(), m_BackgroundMargins.GetBottom()); | ||||
| 						graphics.DrawImage(m_Background, r, 0, m_Background->GetHeight() - m_BackgroundMargins.GetBottom(), m_BackgroundMargins.GetLeft(), m_BackgroundMargins.GetBottom(), UnitPixel); | ||||
| 							Rect r(0, h - m.bottom, m.left, m.bottom); | ||||
| 							graphics.DrawImage(tempBackground, r, 0, m_BackgroundSize.cy - m.bottom, m.left, m.bottom, UnitPixel); | ||||
| 						} | ||||
| 						// Bottom | ||||
| 					Rect r(m_BackgroundMargins.GetLeft(), h - m_BackgroundMargins.GetBottom(), w - m_BackgroundMargins.GetLeft() - m_BackgroundMargins.GetRight(), m_BackgroundMargins.GetBottom()); | ||||
| 					graphics.DrawImage(m_Background, r, m_BackgroundMargins.GetLeft(), m_Background->GetHeight() - m_BackgroundMargins.GetBottom(), m_Background->GetWidth() - m_BackgroundMargins.GetLeft() - m_BackgroundMargins.GetRight(), m_BackgroundMargins.GetBottom(), UnitPixel); | ||||
| 						Rect r(m.left, h - m.bottom, w - m.left - m.right, m.bottom); | ||||
| 						graphics.DrawImage(tempBackground, r, m.left, m_BackgroundSize.cy - m.bottom, m_BackgroundSize.cx - m.left - m.right, m.bottom, UnitPixel); | ||||
|  | ||||
| 					if (m_BackgroundMargins.GetRight() > 0)  | ||||
| 						if (m.right > 0)  | ||||
| 						{ | ||||
| 							// Bottom-Right | ||||
| 						Rect r(w - m_BackgroundMargins.GetRight(), h - m_BackgroundMargins.GetBottom(), m_BackgroundMargins.GetRight(), m_BackgroundMargins.GetBottom()); | ||||
| 						graphics.DrawImage(m_Background, r, m_Background->GetWidth() - m_BackgroundMargins.GetRight(), m_Background->GetHeight() - m_BackgroundMargins.GetBottom(), m_BackgroundMargins.GetRight(), m_BackgroundMargins.GetBottom(), UnitPixel); | ||||
| 							Rect r(w - m.right, h - m.bottom, m.right, m.bottom); | ||||
| 							graphics.DrawImage(tempBackground, r, m_BackgroundSize.cx - m.right, m_BackgroundSize.cy - m.bottom, m.right, m.bottom, UnitPixel); | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					ImageAttributes imgAttr; | ||||
| 					imgAttr.SetWrapMode(WrapModeTile); | ||||
|  | ||||
| 					Rect r(0, 0, w, h); | ||||
| 					graphics.DrawImage(tempBackground, r, 0, 0, w, h, UnitPixel, &imgAttr); | ||||
| 				} | ||||
|  | ||||
| 				delete m_Background; | ||||
| 				m_Background = scaledBackground; | ||||
| 				m_Background = background; | ||||
| 			} | ||||
|  | ||||
| 			// Get the size form the background bitmap | ||||
| @@ -2238,6 +2248,8 @@ bool CMeterWindow::ResizeWindow(bool reset) | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			if (m_WindowW != 0 && m_WindowH != 0) | ||||
| 			{ | ||||
| 				// Create a solid color bitmap for the background | ||||
| 				m_Background = new Bitmap(m_WindowW, m_WindowH, PixelFormat32bppARGB); | ||||
| @@ -2245,8 +2257,7 @@ bool CMeterWindow::ResizeWindow(bool reset) | ||||
|  | ||||
| 				if (m_SolidColor.GetValue() == m_SolidColor2.GetValue()) | ||||
| 				{ | ||||
| 				SolidBrush solid(m_SolidColor); | ||||
| 				graphics.FillRectangle(&solid, 0, 0, m_WindowW, m_WindowH); | ||||
| 					graphics.Clear(m_SolidColor); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| @@ -2270,6 +2281,7 @@ bool CMeterWindow::ResizeWindow(bool reset) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|      | ||||
| 	return true; | ||||
| } | ||||
|   | ||||
| @@ -77,7 +77,8 @@ enum BGMODE | ||||
| 	BGMODE_IMAGE = 0, | ||||
| 	BGMODE_COPY, | ||||
| 	BGMODE_SOLID, | ||||
| 	BGMODE_SCALED_IMAGE | ||||
| 	BGMODE_SCALED_IMAGE, | ||||
| 	BGMODE_TILED_IMAGE | ||||
| }; | ||||
|  | ||||
| enum HIDEMODE | ||||
|   | ||||
| @@ -2843,9 +2843,7 @@ void CRainmeter::ReadGeneralSettings(const std::wstring& iniFile) | ||||
| 	std::wstring area = parser.ReadString(L"Rainmeter", L"DesktopWorkArea", L""); | ||||
| 	if (!area.empty()) | ||||
| 	{ | ||||
| 		RECT r; | ||||
| 		swscanf(area.c_str(), L"%i,%i,%i,%i", &r.left, &r.top, &r.right, &r.bottom); | ||||
| 		m_DesktopWorkAreas[0] = r; | ||||
| 		m_DesktopWorkAreas[0] = parser.ParseRECT(area.c_str()); | ||||
| 		m_DesktopWorkAreaChanged = true; | ||||
| 	} | ||||
|  | ||||
| @@ -2856,9 +2854,7 @@ void CRainmeter::ReadGeneralSettings(const std::wstring& iniFile) | ||||
| 		area = parser.ReadString(L"Rainmeter", buffer, L""); | ||||
| 		if (!area.empty()) | ||||
| 		{ | ||||
| 			RECT r; | ||||
| 			swscanf(area.c_str(), L"%i,%i,%i,%i", &r.left, &r.top, &r.right, &r.bottom); | ||||
| 			m_DesktopWorkAreas[i] = r; | ||||
| 			m_DesktopWorkAreas[i] = parser.ParseRECT(area.c_str()); | ||||
| 			m_DesktopWorkAreaChanged = true; | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -48,10 +48,12 @@ const Gdiplus::ColorMatrix CTintedImage::c_IdentifyMatrix = { | ||||
| ** The constructor. | ||||
| ** | ||||
| ** If disableTransform is true, following configs are ignored: | ||||
| **  - ImageCrop | ||||
| **  - ImageRotate | ||||
| ** | ||||
| */ | ||||
| CTintedImage::CTintedImage(bool disableTransform) : m_DisableTransform(disableTransform), | ||||
| 	m_Crop(-1, -1, -1, -1), | ||||
| 	m_ColorMatrix(c_IdentifyMatrix) | ||||
| { | ||||
| 	SetConfigAttributes(L"Image", L""); | ||||
| @@ -161,7 +163,14 @@ void CTintedImage::LoadImage(const std::wstring& imageName, bool bLoadAlways) | ||||
|  | ||||
| 								if (m_Bitmap && Ok == m_Bitmap->GetLastStatus()) | ||||
| 								{ | ||||
| 									// Check whether the new image needs tinting (or flipping, rotating) | ||||
| 									// 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) | ||||
| 										{ | ||||
| 											m_NeedsCrop = true; | ||||
| 										} | ||||
| 									} | ||||
| 									if (!m_NeedsTinting) | ||||
| 									{ | ||||
| 										if (m_GreyScale || !CompareColorMatrix(m_ColorMatrix, c_IdentifyMatrix)) | ||||
| @@ -212,12 +221,27 @@ void CTintedImage::LoadImage(const std::wstring& imageName, bool bLoadAlways) | ||||
| 		if (m_Bitmap) | ||||
| 		{ | ||||
| 			// We need a copy of the image if has tinting (or flipping, rotating) | ||||
| 			if (m_NeedsTinting || m_NeedsTransform) | ||||
| 			if (m_NeedsCrop || m_NeedsTinting || m_NeedsTransform) | ||||
| 			{ | ||||
| 				if (m_BitmapTint) | ||||
| 				{ | ||||
| 					delete m_BitmapTint; | ||||
| 					m_BitmapTint = NULL; | ||||
| 				} | ||||
|  | ||||
| 				if (m_Bitmap->GetWidth() > 0 && m_Bitmap->GetHeight() > 0) | ||||
| 				{ | ||||
| 					ApplyCrop(); | ||||
|  | ||||
| 					if (!m_BitmapTint || (m_BitmapTint->GetWidth() > 0 && m_BitmapTint->GetHeight() > 0)) | ||||
| 					{ | ||||
| 						ApplyTint(); | ||||
| 				m_NeedsTinting = false; | ||||
|  | ||||
| 						ApplyTransform(); | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				m_NeedsCrop = false; | ||||
| 				m_NeedsTinting = false; | ||||
| 				m_NeedsTransform = false; | ||||
| 			} | ||||
| 		} | ||||
| @@ -228,6 +252,31 @@ void CTintedImage::LoadImage(const std::wstring& imageName, bool bLoadAlways) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| ** ApplyCrop | ||||
| ** | ||||
| ** This will apply the cropping. | ||||
| ** | ||||
| */ | ||||
| void CTintedImage::ApplyCrop() | ||||
| { | ||||
| 	if (m_Crop.Width >= 0 && m_Crop.Height >= 0) | ||||
| 	{ | ||||
| 		if (m_Crop.Width == 0 || m_Crop.Height == 0) | ||||
| 		{ | ||||
| 			m_BitmapTint = new Bitmap(0, 0, PixelFormat32bppARGB);  // create dummy bitmap | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			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); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| ** ApplyTint | ||||
| ** | ||||
| @@ -236,25 +285,32 @@ void CTintedImage::LoadImage(const std::wstring& imageName, bool bLoadAlways) | ||||
| */ | ||||
| void CTintedImage::ApplyTint() | ||||
| { | ||||
| 	if (m_GreyScale || !CompareColorMatrix(m_ColorMatrix, c_IdentifyMatrix)) | ||||
| 	{ | ||||
| 		Bitmap* original = GetImage(); | ||||
|  | ||||
| 		ImageAttributes ImgAttr; | ||||
| 		ImgAttr.SetColorMatrix(&m_ColorMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap); | ||||
|  | ||||
| 	delete m_BitmapTint; | ||||
| 		Rect r(0, 0, original->GetWidth(), original->GetHeight()); | ||||
|  | ||||
| 	Rect r(0, 0, m_Bitmap->GetWidth(), m_Bitmap->GetHeight()); | ||||
| 	m_BitmapTint = new Bitmap(r.Width, r.Height, PixelFormat32bppARGB); | ||||
| 		Bitmap* tint = new Bitmap(r.Width, r.Height, PixelFormat32bppARGB); | ||||
|  | ||||
| 	Graphics graphics(m_BitmapTint); | ||||
| 		Graphics graphics(tint); | ||||
|  | ||||
| 		if (m_GreyScale) | ||||
| 		{ | ||||
| 		Bitmap* gray = TurnGreyscale(m_Bitmap); | ||||
| 			Bitmap* gray = TurnGreyscale(original); | ||||
| 			graphics.DrawImage(gray, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); | ||||
| 			delete gray; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 		graphics.DrawImage(m_Bitmap, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); | ||||
| 			graphics.DrawImage(original, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); | ||||
| 		} | ||||
|  | ||||
| 		delete m_BitmapTint; | ||||
| 		m_BitmapTint = tint; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -290,7 +346,7 @@ void CTintedImage::ApplyTransform() | ||||
| { | ||||
| 	if (m_Rotate != 0.0f) | ||||
| 	{ | ||||
| 		Bitmap* original = (m_BitmapTint) ? m_BitmapTint : m_Bitmap; | ||||
| 		Bitmap* original = GetImage(); | ||||
|  | ||||
| 		REAL originalW = (REAL)original->GetWidth(); | ||||
| 		REAL originalH = (REAL)original->GetHeight(); | ||||
| @@ -331,7 +387,7 @@ void CTintedImage::ApplyTransform() | ||||
| 	} | ||||
| 	else if (m_Flip != RotateNoneFlipNone) | ||||
| 	{ | ||||
| 		Bitmap* original = (m_BitmapTint) ? m_BitmapTint : m_Bitmap; | ||||
| 		Bitmap* original = GetImage(); | ||||
|  | ||||
| 		Rect r(0, 0, original->GetWidth(), original->GetHeight()); | ||||
| 		Bitmap* transform = new Bitmap(r.Width, r.Height, PixelFormat32bppARGB); | ||||
| @@ -364,6 +420,7 @@ void CTintedImage::SetConfigAttributes(const WCHAR* name, const WCHAR* prefix) | ||||
|  | ||||
| 	if (prefix) | ||||
| 	{ | ||||
| 		(m_ConfigImageCrop    = prefix) += L"ImageCrop"; | ||||
| 		(m_ConfigGreyscale    = prefix) += L"Greyscale"; | ||||
| 		(m_ConfigImageTint    = prefix) += L"ImageTint"; | ||||
| 		(m_ConfigImageAlpha   = prefix) += L"ImageAlpha"; | ||||
| @@ -386,11 +443,19 @@ void CTintedImage::SetConfigAttributes(const WCHAR* name, const WCHAR* prefix) | ||||
| 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; | ||||
| 	bool oldGreyScale = m_GreyScale; | ||||
| 	ColorMatrix oldColorMatrix = m_ColorMatrix; | ||||
| 	RotateFlipType oldFlip = m_Flip; | ||||
| 	REAL oldRotate = m_Rotate; | ||||
|  | ||||
| 	if (!m_DisableTransform) | ||||
| 	{ | ||||
| 		m_Crop = parser.ReadRect(section, m_ConfigImageCrop.c_str(), Rect(-1,-1,-1,-1)); | ||||
| 	} | ||||
|  | ||||
| 	m_NeedsCrop = (oldCrop.X != m_Crop.X || oldCrop.Y != m_Crop.Y || oldCrop.Width != m_Crop.Width || oldCrop.Height != m_Crop.Height); | ||||
|  | ||||
| 	m_GreyScale = 0!=parser.ReadInt(section, m_ConfigGreyscale.c_str(), 0); | ||||
|  | ||||
| 	Color tint = parser.ReadColor(section, m_ConfigImageTint.c_str(), Color::White); | ||||
|   | ||||
| @@ -33,8 +33,8 @@ public: | ||||
|  | ||||
| 	bool IsLoaded() { return (m_Bitmap != NULL); } | ||||
| 	bool IsTinted() { return (m_BitmapTint != NULL); } | ||||
| 	bool IsConfigsChanged() { return m_NeedsTinting || m_NeedsTransform; } | ||||
| 	void ClearConfigFlags() { m_NeedsTinting = m_NeedsTransform = false; } | ||||
| 	bool IsConfigsChanged() { return m_NeedsCrop || m_NeedsTinting || m_NeedsTransform; } | ||||
| 	void ClearConfigFlags() { m_NeedsCrop = m_NeedsTinting = m_NeedsTransform = false; } | ||||
|  | ||||
| 	Gdiplus::Bitmap* GetOriginalImage() { return m_Bitmap; } | ||||
| 	Gdiplus::Bitmap* GetTintedImage() { return m_BitmapTint; } | ||||
| @@ -44,6 +44,7 @@ public: | ||||
| 	void LoadImage(const std::wstring& imageName, bool bLoadAlways); | ||||
|  | ||||
| protected: | ||||
| 	void ApplyCrop(); | ||||
| 	void ApplyTint(); | ||||
| 	void ApplyTransform(); | ||||
|  | ||||
| @@ -57,6 +58,7 @@ protected: | ||||
| 	FILETIME m_Modified; | ||||
|  | ||||
| 	std::wstring m_ConfigName; | ||||
| 	std::wstring m_ConfigImageCrop; | ||||
| 	std::wstring m_ConfigGreyscale; | ||||
| 	std::wstring m_ConfigImageTint; | ||||
| 	std::wstring m_ConfigImageAlpha; | ||||
| @@ -70,9 +72,11 @@ protected: | ||||
|  | ||||
| 	const bool m_DisableTransform; | ||||
|  | ||||
| 	bool m_NeedsCrop; | ||||
| 	bool m_NeedsTinting; | ||||
| 	bool m_NeedsTransform; | ||||
|  | ||||
| 	Gdiplus::Rect m_Crop; | ||||
| 	bool m_GreyScale; | ||||
| 	Gdiplus::ColorMatrix m_ColorMatrix; | ||||
| 	Gdiplus::RotateFlipType m_Flip; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 spx
					spx