Visual Studio 2003插件的编写(三)

上一篇介绍了Resource排序器的接口设计,这次会把具体的实现进行说明。

Resource排序器主要是将Resource.h里面的ID进行排序。只是需要注意的是该文件中有几个宏定义:APS_NEXT_RESOURCE_VALUE, APS_NEXT_COMMAND_VALUE,_APS_NEXT_CONTROL_VALUE, _APS_NEXT_SYMED_VALUE。因为每在rc文件里面添加一个资源(对话框),都会在resource.h里面自动生成一个ID值,但它怎么知道应该生成的值是多少呢?就是去读这几个宏定义的。然后每次在resource.h里面生成一个ID后,相对应的宏的值就会+1。具体每个宏是什么意思可以参考MSDN文章:Using Multiple Resource Files and Header Files with Visual C++。

为了使用的方便,首先用一个Define类f这些宏定义和换行符等东西

	public class Define

	{

		public const string _APS_NEXT_RESOURCE_VALUE_STR = "_APS_NEXT_RESOURCE_VALUE";

		public const string _APS_NEXT_COMMAND_VALUE_STR  = "_APS_NEXT_COMMAND_VALUE";

		public const string _APS_NEXT_CONTROL_VALUE_STR  = "_APS_NEXT_CONTROL_VALUE";

		public const string _APS_NEXT_SYMED_VALUE_STR    = "_APS_NEXT_SYMED_VALUE";

		

		// _APS_NEXT_RESOURCE_VALUE的范围

		public const long _APS_NEXT_RESOURCE_VALUE_BEGIN = 1;

		public const long _APS_NEXT_RESOURCE_VALUE_END   = 0x6FFF;



		// _APS_NEXT_COMMAND_VALUE的范围

		public const long _APS_NEXT_COMMAND_VALUE_BEGIN  = 0x8000;

		public const long _APS_NEXT_COMMAND_VALUE_END    = 0xDFFF;



		// _APS_NEXT_CONTROL_VALUE的范围

		public const long _APS_NEXT_CONTROL_VALUE_BEGIN  = 8;

		public const long _APS_NEXT_CONTROL_VALUE_END    = 0xDFFF;



		// 几个换行符

		public const string CLRF                         = "/r/n";

		public const string CL                           = "/r";

		public const string RF                           = "/n";



		public const string RESOURCE_NAME                = "resource.h";	

	}

最后就是的ResoureParse类了,需要处理注意的有下面几个地方: 1.不同的资源类型是有区间范围的,例如Dialog, Menu和IDD_开头的普通控件就在不同的区间。因此   ID递增的时候必须在各自的区间内(就是上面所说的宏,换句话说上面的宏就应该是该区间的最大值   再加一)。 2.Int.Parse函数是不支持"0x"开头的16进制数字,因此要去掉0x前缀进行处理。

using System;

using System.Text;

using System.IO;



namespace Commands.FileParser

{

	/// <summary>

	/// ResourceParser 的摘要说明。

	/// </summary>

	public class ResourceParser: IParser

	{

		private long m_counter                 = 0;

		private long m_last                    = 1;

		private long m_APS_NEXT_RESOURCE_VALUE = 0;

		private long m_APS_NEXT_COMMAND_VALUE  = 0;

		private long m_APS_NEXT_CONTROL_VALUE  = 0;

		//private long m_APS_NEXT_SYMED_VALUE  = 0;

		public ResourceParser()

		{



		}



		// 函数名: ParseLine

		// 参数:   line 被解析的字符串

		// 描述:   解析传入的一行字符串,并调整资源ID的值

		void ParseLine(ref string line)

		{

			// 首先找到#define 字段

			int pos = line.IndexOf("#define");

			if (pos == -1)

			{

				return;

			}



			// 再找到最后一个空格

			pos = line.LastIndexOf(' ');

			if (pos == -1)

			{

				return;

			}



			// 如果是_APS_NEXT开头的几个宏要进行格外处理

			if (!ParseAPS_NEXTLine(ref line))

			{

				// 将最后一个ID逐行加1再替换

				string oldNumber = line.Substring(pos + 1);

				string newNumber = GetLineIndex(NumberToInt(oldNumber)).ToString();

				line = line.Replace(oldNumber, newNumber);

			}

		}



		// 函数名: ParseNumber

		// 参数:   oldNumber 需要转换的字符串

		// 描述:   字符串转换成整形,并一并处理16进制的情况

		private int NumberToInt( string oldNumber )

		{

			int HexPos = oldNumber.IndexOf("0x");

			

			int Value = 0;

			//不是以Hex开头的字符串

			if (HexPos == -1)

			{

				Value = int.Parse(oldNumber);	

			}

			else

			{

				string HexNumber = oldNumber.Remove(HexPos, 2);

				Value = Int32.Parse(HexNumber, System.Globalization.NumberStyles.AllowHexSpecifier);

			}

			return Value;

		}



		// 函数名: IsAPSLine

		// 参数:   line 被解析的字符串

		// 描述:   解析传入的一行字符串,并调整资源ID的值

		bool ParseAPS_NEXTLine(ref string line)

		{

			int pos = line.LastIndexOf(' ');



			bool found = true;

			

			string oldNumber = line.Substring(pos);

			if (line.IndexOf(Define._APS_NEXT_RESOURCE_VALUE_STR) != -1)

			{

				line = line.Replace(oldNumber, m_APS_NEXT_RESOURCE_VALUE.ToString());

			}

			else if (line.IndexOf(Define._APS_NEXT_CONTROL_VALUE_STR) != -1)

			{

				line = line.Replace(oldNumber, m_APS_NEXT_CONTROL_VALUE.ToString());

			}

			else if (line.IndexOf(Define._APS_NEXT_COMMAND_VALUE_STR) != -1)

			{

				line = line.Replace(oldNumber, m_APS_NEXT_CONTROL_VALUE.ToString());

			}

			else if (line.IndexOf(Define._APS_NEXT_SYMED_VALUE_STR) != -1)

			{

				// Do nothing

			}

			else

			{

				found = false;

			}



			return found;

		}



		// 函数名: GetRange

		// 参数:   number 

		// 描述:   获得该数字所属的区间

		//         < 100, 返回100

		//         100 <= && < 1000, 返回1000

		//         >= 1000 && <10000, 返回10000

		//         >10000, 直接返回10000

		long GetRange(long number)

		{

			long range = 1;



			if (number < 100)

			{

				range = 1;

			}

			else if (number >= 100 && number < 1000)

			{

				range = 100;

			}

			else if (number >= 1000 && number < 10000)

			{

				range = 1000;

			}

			else if (number >= 10000 && number < Define._APS_NEXT_COMMAND_VALUE_BEGIN)

			{

				range = 10000;

			}

			else

			{

				range = number;

			}



			return range;

		}



		// 函数名: GetLineIndex

		// 参数:   void

		// 描述:   每有一个新的#define ID xxx,数字就加1

		long GetLineIndex(long number)

		{

			// 记录上一次的range

			

			long range = GetRange(number);

			if (m_last != range)

			{

				m_counter = 0;

				m_last = range;

			}

		

			m_counter++;



			long result = m_counter + range;	

			if (result < 1000)

			{

				m_APS_NEXT_RESOURCE_VALUE = result + 1;

			}

			else if (result >= 1000 && result < Define._APS_NEXT_COMMAND_VALUE_BEGIN)

			{

				m_APS_NEXT_CONTROL_VALUE = result + 1;

			}

			else if (result >= Define._APS_NEXT_COMMAND_VALUE_BEGIN)

			{

				m_APS_NEXT_COMMAND_VALUE  = result + 1;

			}



			return result;

		}

			

		#region IParser 成员





		public int Parse(string fileName)

		{

			string line;

			StringBuilder sb = new StringBuilder();			

			using (System.IO.StreamReader reader = new System.IO.StreamReader(fileName))

			{

				while((line = reader.ReadLine()) != null)

				{

					ParseLine(ref line);

					sb.Append(line);

					sb.Append(Define.CLRF);

				}

				sb.Append(Define.RF);

				reader.Close();

			}





			File.SetAttributes(fileName,FileAttributes.Normal);

		

			// TODO:  添加 ResourceParser.Parse 实现

			using (StreamWriter outWriter = new StreamWriter(fileName))

			{

				outWriter.Write(sb.ToString());		

			}

			return 0;

		}



		/// <summary>

		/// 应用程序的主入口点。

		/// </summary>

		[STAThread]

		static void Main(string[] args)

		{

			//

			// TODO: 在此处添加代码以启动应用程序

			//

			ResourceParser parser = new ResourceParser();

			parser.Parse("resource.h");

		}



		#endregion

	}

}
这篇文章写得比较懒,因为比较不喜欢一行一行的说代码,每个人的想法都不一样。还是那句话,只要
接口定义出来了,具体里面的实现就不会差到哪儿去。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值