⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rcctrlparser.cpp

📁 壓縮及解壓縮的原始碼(Microsoft visual c++)
💻 CPP
字号:
// RCCtrlParser.cpp: implementation of the CRCCtrlParser class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "RCCtrlParser.h"
#include "winstyles.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////

enum RCTYPE
{
	AUTO3STATE,
	AUTOCHECKBOX,
	AUTORADIOBUTTON,
	CHECKBOX,
	COMBOBOX,
	CONTROL,
	CTEXT,
	DEFPUSHBUTTON,
	EDITTEXT,
	GROUPBOX,
	ICON,
	LISTBOX,
	LTEXT,
	PUSHBOX,
	PUSHBUTTON,
	RADIOBUTTON,
	RTEXT,
	SCROLLBAR,
	STATE3, 
};

struct RCCTRLTYPE
{
	LPCTSTR szType;
	RCTYPE nType;
	LPCTSTR szClass;
	DWORD dwDefStyle;
};

#define MAKERCTYPE(type) #type, (RCTYPE)type 

static RCCTRLTYPE RCCTRLTYPES[] = 
{
	{ MAKERCTYPE(AUTO3STATE), "button", BS_AUTO3STATE | WS_TABSTOP },
	{ MAKERCTYPE(AUTOCHECKBOX), "button", BS_AUTOCHECKBOX | WS_TABSTOP },
	{ MAKERCTYPE(AUTORADIOBUTTON), "button", BS_AUTORADIOBUTTON | WS_TABSTOP },
	{ MAKERCTYPE(CHECKBOX), "button", BS_CHECKBOX | WS_TABSTOP },
	{ MAKERCTYPE(COMBOBOX), "combobox", CBS_SIMPLE | WS_TABSTOP },
	{ MAKERCTYPE(CONTROL), NULL, 0 },
	{ MAKERCTYPE(CTEXT), "static", SS_CENTER | WS_GROUP }, 
	{ MAKERCTYPE(DEFPUSHBUTTON), "button", BS_DEFPUSHBUTTON | WS_TABSTOP },
	{ MAKERCTYPE(EDITTEXT), "edit", ES_LEFT | WS_BORDER | WS_TABSTOP },
	{ MAKERCTYPE(GROUPBOX), "button", BS_GROUPBOX },
	{ MAKERCTYPE(ICON), "static", SS_ICON },
	{ MAKERCTYPE(LISTBOX), "listbox", LBS_NOTIFY | WS_BORDER },
	{ MAKERCTYPE(LTEXT), "static", SS_LEFT | WS_GROUP },
	{ MAKERCTYPE(PUSHBOX), "button", /*BS_PUSHBOX | */WS_TABSTOP },
	{ MAKERCTYPE(PUSHBUTTON), "button", BS_PUSHBUTTON | WS_TABSTOP },
	{ MAKERCTYPE(RADIOBUTTON), "button", BS_RADIOBUTTON | WS_TABSTOP },
	{ MAKERCTYPE(RTEXT), "static", SS_RIGHT | WS_GROUP },
	{ MAKERCTYPE(SCROLLBAR), "scrollbar", SBS_HORZ },
	{ MAKERCTYPE(STATE3), "button", BS_3STATE | WS_TABSTOP }, 
};

const int NUMRCTYPES = sizeof(RCCTRLTYPES) / sizeof(RCCTRLTYPE);

/////////////////////////////////////////////////////////////////////////////

// list of classes requiring WS_EX_CLIENTEDGE by default

static LPCTSTR szCtrlsWantingClientEdge[] = 
{
	"Edit",
	"ComboBox",
	"ComboLBox",
	"ListBox",
	"msctls_hotkey32",
	"SysListView32",
	"SysTreeView32",
	"Richedit",
	"SysDateTimePick32",
	"SysIPAddress32",
	"SysPager32",
	"ComboBoxEx32",
//	"Button", 
//	"Static",
//	"Scrollbar",
//	"toolbarwindow32",
//	"msctls_updown32",
//	"msctls_progress32",
//	"msctls_trackbar32",
//	"SysTabControl32",
//	"SysAnimate32",
//	"SysMonthCal32",
//	"msctls_statusbar32",
//	"ReBarWindow32",
//	"SysHeader32",
//	"tooltips_class32",
};

/////////////////////////////////////////////////////////////////////////////

// see ParseRCStyles() for what this is about
#define WS_NOTVISIBLE WS_POPUP

/////////////////////////////////////////////////////////////////////////////

CRCCtrlParser::CRCCtrlParser(LPCTSTR szRCControls)
{
	if (szRCControls)
		ParseRCControls(szRCControls);
}

CRCCtrlParser::~CRCCtrlParser()
{

}

int CRCCtrlParser::ParseRCControls(const CString& sRCControls)
{
	m_lstControls.RemoveAll();

	// parse the text control by control
	int nStart = 0, nEnd = -1, nCount = 0;

	do
	{
		nEnd = FindNextRCControl(sRCControls, nStart ? nStart + 1 : 0);
		CString sRCCtrl = nEnd != -1 ? sRCControls.Mid(nStart, nEnd - nStart - 1) : sRCControls.Mid(nStart);

		sRCCtrl.TrimLeft();
		sRCCtrl.TrimRight();

		AddRCControl(sRCCtrl);

		nStart = nEnd;
	}
	while (nEnd != -1);

	return m_lstControls.GetCount();
}

int CRCCtrlParser::GetRCControls(CRTCtrlList& lstControls) const
{
	lstControls.AddTail((CRTCtrlList*)&m_lstControls);

	return m_lstControls.GetCount();
}

BOOL CRCCtrlParser::AddRCControl(const CString& sRCCtrl)
{
	CString sCaption;
	UINT uID = 0;
	CString sClass;
	DWORD dwStyle = 0;
	POINT pos = { 0, 0 };
	SIZE size = { 0, 0 };
	DWORD dwExStyle = 0;
	UINT nIconID;

	int nType = ParseRCControl(sRCCtrl, sCaption, uID, sClass, dwStyle, pos, size, dwExStyle, nIconID);
	
	if (nType == -1)
		return FALSE;

	RTCONTROL rtc(NULL, sClass, sCaption, dwStyle, dwExStyle, CRect(pos, size), uID, TRUE);
	rtc.m_nIconID = nIconID;

	return (NULL != m_lstControls.AddTail(rtc));
}

int CRCCtrlParser::FindNextRCControl(const CString& sRCControls, int nStart)
{
	int nType = NUMRCTYPES, nFirstType = -1, nFirstFind = -1;

	while (nType--)
	{
		int nFind = sRCControls.Find(RCCTRLTYPES[nType].szType, nStart);

		if (nFind != -1 && (nFind < nFirstFind || nFirstType == -1) && (nFind == 0 || isspace(sRCControls[nFind - 1])))
		{
			nFirstType = RCCTRLTYPES[nType].nType;
			nFirstFind = nFind;
		}
	}

	return nFirstFind;
}

int CRCCtrlParser::ParseRCControl(const CString& sRCCtrl, CString& sCaption, UINT& uID, CString& sClass, 
								  DWORD& dwStyle, POINT& pos, SIZE& size, DWORD& dwExStyle, UINT& nIconID)
{
	int nIndex = GetRCControlTypeIndex(sRCCtrl);

	if (nIndex == -1)
		return -1;

	CString sID, sStyle, sX, sY, sCx, sCy, sExStyle, sIconID;

	switch (RCCTRLTYPES[nIndex].nType)
	{
	// 'CONTROL' definitions always take the same form:

	// caption, id, class, style, x, y, cx, cy, exstyle
	case CONTROL:
		{
			CString* pItems[] = { &sCaption, &sID, &sClass, &sStyle, &sX, &sY, &sCx, &sCy, &sExStyle };
			ExtractRCItems(sRCCtrl, RCCTRLTYPES[nIndex].szType, pItems, sizeof(pItems) / sizeof(CString*));
		}
		break;

	// older window control definitions have 3 forms:

	// 1. caption, id, x, y, cx, cy, style, exstyle
	case AUTO3STATE:
	case AUTOCHECKBOX:
	case AUTORADIOBUTTON:
	case CHECKBOX:
	case CTEXT:
	case DEFPUSHBUTTON:
	case GROUPBOX:
	case LTEXT:
	case PUSHBOX:
	case PUSHBUTTON:
	case RADIOBUTTON:
	case RTEXT:
	case STATE3:
		{
			CString* pItems[] = { &sCaption, &sID, &sX, &sY, &sCx, &sCy, &sStyle, &sExStyle };
			ExtractRCItems(sRCCtrl, RCCTRLTYPES[nIndex].szType, pItems, sizeof(pItems) / sizeof(CString*));
		}
		break;
		
	// 2. id, x, y, cx, cy, style, exstyle
	case SCROLLBAR:
	case COMBOBOX:
	case EDITTEXT:
	case LISTBOX:
		{
			CString* pItems[] = { &sID, &sX, &sY, &sCx, &sCy, &sStyle, &sExStyle };
			ExtractRCItems(sRCCtrl, RCCTRLTYPES[nIndex].szType, pItems, sizeof(pItems) / sizeof(CString*));
		}
		break;

	// 3. iconid, id, x, y, cx, cy
	case ICON:
		{
			CString* pItems[] = { &sIconID, &sID, &sX, &sY, &sCx, &sCy };
			ExtractRCItems(sRCCtrl, RCCTRLTYPES[nIndex].szType, pItems, sizeof(pItems) / sizeof(CString*));
		}
		break;
	
	default:
		nIndex = -1;
	}

	// global settings
	if (nIndex != -1)
	{
		// class names for predefined classes
		if (sClass.IsEmpty())
			sClass = RCCTRLTYPES[nIndex].szClass;

		// styles
		dwStyle = ParseRCStyles(sClass, sStyle);
		dwExStyle = ParseRCExStyles(sClass, sExStyle);

		// handle invisibility
		BOOL bVisible = !(dwStyle & WS_NOTVISIBLE);
		dwStyle &= ~WS_NOTVISIBLE;

		// default styles if no styles specified
		if (!dwStyle)
			dwStyle = RCCTRLTYPES[nIndex].dwDefStyle;

		dwStyle |= WS_CHILD | (bVisible ? WS_VISIBLE : 0); // always

		// add client-edge depending on class name
		if (CtrlWantsClientEdge(sClass))
			dwExStyle |= WS_EX_CLIENTEDGE;

		uID = atoi(sID);
		pos.x = atoi(sX);
		pos.y = atoi(sY);
		size.cx = atoi(sCx);
		size.cy = atoi(sCy);
		nIconID = atoi(sIconID);
	}

	return nIndex;
}

void CRCCtrlParser::ExtractRCItems(const CString& sRCCtrl, LPCTSTR szType, CString* pItems[], int nMaxItems)
{
	CString sTemp(sRCCtrl);

	sTemp = sTemp.Mid(lstrlen(szType));
	sTemp.TrimLeft();

	int nItem = 0;

	while (nItem < nMaxItems)
	{
		// if the first char is a double quote then we need to ignore 
		// commas till we find the end quote
		int nStart = 0;

		if (sTemp[0] == '\"')
			nStart = sTemp.Find('\"', 1);

		int nFind = sTemp.Find(',', nStart);

		if (nFind == -1)
		{
			*pItems[nItem] = sTemp;
			pItems[nItem]->Replace("\"", "");

			break;
		}

		// else
		*pItems[nItem] = sTemp.Left(nFind);
		pItems[nItem]->Replace("\"", "");

		sTemp = sTemp.Mid(nFind + 1);
		sTemp.TrimLeft();

		nItem++;
	}
}

int CRCCtrlParser::GetRCControlTypeIndex(const CString& sRCCtrl)
{
	int nType = NUMRCTYPES;

	while (nType--)
	{
		if (0 == sRCCtrl.Find(RCCTRLTYPES[nType].szType))
			return nType;
	}

	return -1;
}

DWORD CRCCtrlParser::ParseRCStyles(LPCTSTR szClass, const CString& sStyle)
{
	CStringArray aStyles;
	DWORD dwStyle = 0;

	if (ExtractRCStyles(sStyle, aStyles))
	{
		int nStyle = aStyles.GetSize();

		while (nStyle--)
		{
			// note: invisible controls are handled via 'NOT WS_VISIBLE'
			// so we must handle this explicitly via a hack
			// we can reuse WS_POPUP because this will _never_ appear for 
			// a child control (i hope)
			if (CString(aStyles[nStyle]).CompareNoCase("NOT WS_VISIBLE") == 0)
				dwStyle |= WS_NOTVISIBLE;
			else
			{
				dwStyle |= LookupWndStyle(aStyles[nStyle]);
				dwStyle |= LookupCtrlStyle(aStyles[nStyle]);
			}
		}
	}

	return dwStyle;
}

DWORD CRCCtrlParser::ParseRCExStyles(LPCTSTR szClass, const CString& sExStyle)
{
	CStringArray aExStyles;
	DWORD dwExStyle = 0;

	if (ExtractRCStyles(sExStyle, aExStyles))
	{
		int nExStyle = aExStyles.GetSize();

		while (nExStyle--)
		{
			dwExStyle |= LookupWndExStyle(aExStyles[nExStyle]);
			dwExStyle |= LookupCtrlStyle(aExStyles[nExStyle]);
		}
	}

	return dwExStyle;
}

int CRCCtrlParser::ExtractRCStyles(const CString& sStyles, CStringArray& aStyles)
{
	// styles are delimetered by '|'
	CString sTemp(sStyles);
	sTemp.TrimLeft();

	do
	{
		int nFind = sTemp.Find('|');

		if (nFind == -1)
		{
			sTemp.TrimRight();

			if (sTemp.GetLength())
				aStyles.Add(sTemp);
			break;
		}
		else
		{
			CString sStyle = sTemp.Left(nFind);
			sStyle.TrimRight();

			sTemp = sTemp.Mid(nFind + 1);
			sTemp.TrimLeft();

			if (sStyle.GetLength())
				aStyles.Add(sStyle);
		}

	}
	while (TRUE);

	return aStyles.GetSize();
}

BOOL CRCCtrlParser::CtrlWantsClientEdge(LPCTSTR szClass)
{
	int nClass = sizeof(szCtrlsWantingClientEdge) / sizeof(LPCTSTR);
	CString sClass(szClass);

	while (nClass--)
	{
		if (sClass.CompareNoCase(szCtrlsWantingClientEdge[nClass]) == 0)
			return TRUE;
	}

	return FALSE; // no match
}

DWORD CRCCtrlParser::GetDefaultStyles(LPCTSTR szRCType)
{
	int nType = NUMRCTYPES;

	while (nType--)
	{
		if (stricmp(RCCTRLTYPES[nType].szType, szRCType) == 0)
			return RCCTRLTYPES[nType].dwDefStyle;
	}

	return 0;
}

BOOL CRCCtrlParser::GetClassName(LPCTSTR szRCType, CString& sClass)
{
	int nType = NUMRCTYPES;

	while (nType--)
	{
		if (stricmp(RCCTRLTYPES[nType].szType, szRCType) == 0)
		{
			sClass = RCCTRLTYPES[nType].szClass;
			return TRUE;
		}
	}

	return FALSE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -