Click here to Skip to main content
15,886,718 members
Articles / Programming Languages / C#

Visual Studio Add-in that produces compact HTML code documentation

Rate me:
Please Sign up or sign in to vote.
3.00/5 (2 votes)
5 Aug 2005CPOL4 min read 35.4K   235   16  
A Visual Studio add-in that produces compact HTML code documentation from embedded XML.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
using EnvDTE;

namespace VShtmlhelp
{
	/// <summary>
	/// Summary description for HelpDialog.
	/// </summary>
	public class HelpDialog : System.Windows.Forms.Form
	{
		const string imageDir = "images";
		const string classDir = "classes";
		const string className = "Class";

		private int classCount = 1;			// index count for class files

		public _DTE dteApplication;

		protected internal System.Windows.Forms.FolderBrowserDialog folderBrowserDialog;

		private System.Windows.Forms.Button closeBtn;
		private System.Windows.Forms.ListBox projectsLst;
		private System.Windows.Forms.Label projectsLbl;
		private System.Windows.Forms.TreeView filesTrv;
		private System.Windows.Forms.Label filesLbl;
		private System.Windows.Forms.Label solutionNameLbl;
		private System.Windows.Forms.Label solutionLbl;
		private System.Windows.Forms.TextBox saveTbx;
		private System.Windows.Forms.Label saveLbl;
		private System.Windows.Forms.Button browseBtn;
		private System.Windows.Forms.Button buildBtn;
		
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public HelpDialog()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(HelpDialog));
			this.closeBtn = new System.Windows.Forms.Button();
			this.projectsLst = new System.Windows.Forms.ListBox();
			this.projectsLbl = new System.Windows.Forms.Label();
			this.filesTrv = new System.Windows.Forms.TreeView();
			this.filesLbl = new System.Windows.Forms.Label();
			this.solutionNameLbl = new System.Windows.Forms.Label();
			this.solutionLbl = new System.Windows.Forms.Label();
			this.saveTbx = new System.Windows.Forms.TextBox();
			this.saveLbl = new System.Windows.Forms.Label();
			this.browseBtn = new System.Windows.Forms.Button();
			this.buildBtn = new System.Windows.Forms.Button();
			this.SuspendLayout();
			// 
			// closeBtn
			// 
			this.closeBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
			this.closeBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
			this.closeBtn.Location = new System.Drawing.Point(352, 400);
			this.closeBtn.Name = "closeBtn";
			this.closeBtn.TabIndex = 0;
			this.closeBtn.Text = "Close";
			// 
			// projectsLst
			// 
			this.projectsLst.Location = new System.Drawing.Point(16, 72);
			this.projectsLst.Name = "projectsLst";
			this.projectsLst.Size = new System.Drawing.Size(120, 95);
			this.projectsLst.TabIndex = 13;
			this.projectsLst.SelectedIndexChanged += new System.EventHandler(this.projectsLst_SelectedIndexChanged);
			// 
			// projectsLbl
			// 
			this.projectsLbl.Location = new System.Drawing.Point(16, 48);
			this.projectsLbl.Name = "projectsLbl";
			this.projectsLbl.Size = new System.Drawing.Size(112, 23);
			this.projectsLbl.TabIndex = 15;
			this.projectsLbl.Text = "Projects In Solution";
			// 
			// filesTrv
			// 
			this.filesTrv.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
				| System.Windows.Forms.AnchorStyles.Left) 
				| System.Windows.Forms.AnchorStyles.Right)));
			this.filesTrv.ImageIndex = -1;
			this.filesTrv.Indent = 25;
			this.filesTrv.Location = new System.Drawing.Point(160, 72);
			this.filesTrv.Name = "filesTrv";
			this.filesTrv.SelectedImageIndex = -1;
			this.filesTrv.Size = new System.Drawing.Size(264, 256);
			this.filesTrv.TabIndex = 16;
			// 
			// filesLbl
			// 
			this.filesLbl.Location = new System.Drawing.Point(160, 48);
			this.filesLbl.Name = "filesLbl";
			this.filesLbl.Size = new System.Drawing.Size(128, 23);
			this.filesLbl.TabIndex = 17;
			this.filesLbl.Text = "Project Structure";
			// 
			// solutionNameLbl
			// 
			this.solutionNameLbl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
				| System.Windows.Forms.AnchorStyles.Right)));
			this.solutionNameLbl.Location = new System.Drawing.Point(104, 16);
			this.solutionNameLbl.Name = "solutionNameLbl";
			this.solutionNameLbl.Size = new System.Drawing.Size(320, 32);
			this.solutionNameLbl.TabIndex = 19;
			// 
			// solutionLbl
			// 
			this.solutionLbl.Location = new System.Drawing.Point(16, 16);
			this.solutionLbl.Name = "solutionLbl";
			this.solutionLbl.Size = new System.Drawing.Size(80, 23);
			this.solutionLbl.TabIndex = 18;
			this.solutionLbl.Text = "Solution Name";
			// 
			// saveTbx
			// 
			this.saveTbx.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
				| System.Windows.Forms.AnchorStyles.Right)));
			this.saveTbx.Location = new System.Drawing.Point(16, 360);
			this.saveTbx.Name = "saveTbx";
			this.saveTbx.Size = new System.Drawing.Size(328, 20);
			this.saveTbx.TabIndex = 21;
			this.saveTbx.Text = "";
			// 
			// saveLbl
			// 
			this.saveLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
			this.saveLbl.Location = new System.Drawing.Point(16, 336);
			this.saveLbl.Name = "saveLbl";
			this.saveLbl.Size = new System.Drawing.Size(120, 24);
			this.saveLbl.TabIndex = 20;
			this.saveLbl.Text = "Save HTML pages in:";
			// 
			// browseBtn
			// 
			this.browseBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
			this.browseBtn.Location = new System.Drawing.Point(352, 360);
			this.browseBtn.Name = "browseBtn";
			this.browseBtn.TabIndex = 22;
			this.browseBtn.Text = "Browse";
			this.browseBtn.Click += new System.EventHandler(this.browseBtn_Click);
			// 
			// buildBtn
			// 
			this.buildBtn.Location = new System.Drawing.Point(256, 400);
			this.buildBtn.Name = "buildBtn";
			this.buildBtn.TabIndex = 23;
			this.buildBtn.Text = "Build";
			this.buildBtn.Click += new System.EventHandler(this.buildBtn_Click);
			// 
			// HelpDialog
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(448, 438);
			this.Controls.Add(this.buildBtn);
			this.Controls.Add(this.browseBtn);
			this.Controls.Add(this.saveTbx);
			this.Controls.Add(this.saveLbl);
			this.Controls.Add(this.solutionNameLbl);
			this.Controls.Add(this.solutionLbl);
			this.Controls.Add(this.filesLbl);
			this.Controls.Add(this.filesTrv);
			this.Controls.Add(this.projectsLbl);
			this.Controls.Add(this.projectsLst);
			this.Controls.Add(this.closeBtn);
			this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
			this.MaximumSize = new System.Drawing.Size(456, 472);
			this.MinimumSize = new System.Drawing.Size(456, 472);
			this.Name = "HelpDialog";
			this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
			this.Text = "HTML Help";
			this.Load += new System.EventHandler(this.HelpDialog_Load);
			this.ResumeLayout(false);

		}
		#endregion

		#region Programme event methods
		/// <summary>
		/// Help Dialog load event.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void HelpDialog_Load(object sender, System.EventArgs e)
		{	
			EnvDTE.Solution dteSolution = dteApplication.Solution;

			solutionNameLbl.Text = dteSolution.FullName;
			LoadSolutionProjects(dteSolution);

			string fullpathStr = dteSolution.FullName;
			string[] tmp = fullpathStr.Split("\\".ToCharArray());
			string temp = tmp[tmp.Length -1];
			fullpathStr = fullpathStr.TrimEnd(temp.ToCharArray());

			Directory.SetCurrentDirectory(fullpathStr);
			saveTbx.Text = Directory.GetCurrentDirectory();
		}

		/// <summary>
		/// Folder browse dialog event.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void browseBtn_Click(object sender, System.EventArgs e)
		{
			this.folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();

			if (folderBrowserDialog.ShowDialog() == DialogResult.OK) 
			{
				saveTbx.Text = folderBrowserDialog.SelectedPath;
			}
		}

		/// <summary>
		/// View the selected project (projectsLst) event.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void projectsLst_SelectedIndexChanged(object sender, System.EventArgs e)
		{
			EnvDTE.Solution dteSolution = dteApplication.Solution;

			foreach(Project project in dteSolution.Projects)
			{
				if(project.Name == projectsLst.SelectedItem.ToString())
				{
					ProjectItems(project, filesTrv);
					break;
				}
			}
		}

		/// <summary>
		/// Build HTML pages event.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void buildBtn_Click(object sender, System.EventArgs e)
		{
			if (projectsLst.Items.Count != 0)
			{
				EnvDTE.Solution dteSolution = dteApplication.Solution;

				foreach(Project project in dteSolution.Projects)
				{
					if(project.Name == projectsLst.SelectedItem.ToString())
					{
						WriteHtmlLeftPage(filesTrv);
						break;
					}
				}
				Close();
			}
		}
		#endregion

		#region Treeview generation methods
		/// <summary>
		/// Adds all Solution projects to the dialog list box (projectsLst).
		/// </summary>
		/// <param name="dteSolution"></param>
		private void LoadSolutionProjects(Solution dteSolution)
		{
			bool projSelected = false;

			foreach (Project project in dteSolution.Projects)
			{
				// if project does not contain valid code then ignore the project entry
				if (project.ProjectItems != null)
				{
					projectsLst.Items.Add(project.Name);
					if (!projSelected)
					{
						projectsLst.SetSelected(0, true);	// generates projectsLst_SelectedIndexChanged event
						projSelected = true;
					}
				}
			}
		}
		
		/// <summary>
		/// For the selected project cycle through each project item.
		/// </summary>
		/// <param name="project"></param>
		/// <param name="filesTrv"></param>
		private void ProjectItems(Project project, TreeView filesTrv)
		{
			ProjectItem projectItem, tmpProjItem;
			FileCodeModel fileCode;  

			// Clear tree view.
			filesTrv.Nodes.Clear();

			// For the selected Project Cycle each project item.
			for (int r = 1; r< project.ProjectItems.Count +1; r++)
			{
				projectItem = project.ProjectItems.Item(r);
				// Get the file code model
				fileCode = projectItem.FileCodeModel;
				// valid file if not a null
				if (fileCode != null)
				{
					// Cycle through the file code model
					iterateFileCodeModel(fileCode, filesTrv);
				}
					// cycle through items within a folder
				else if (projectItem.ProjectItems.Count > 0)
				{
					tmpProjItem = projectItem;
					for (int s=1; s< tmpProjItem.ProjectItems.Count +1; s++)
					{
						projectItem = tmpProjItem.ProjectItems.Item(s);
						// Get the file code model
						fileCode = projectItem.FileCodeModel;
						if (fileCode != null)
						{
							// Cycle through the file code model
							iterateFileCodeModel(fileCode, filesTrv);
						}
					}
				}
			}
			// Expand the tree view, goto to top of the tree
			filesTrv.ExpandAll();
			filesTrv.SelectedNode = filesTrv.Nodes[0];
		}

		/// <summary>
		/// For the selected project item cycle through the file code model to get code types.
		/// </summary>
		/// <param name="fileCode"></param>
		/// <param name="filesTrv"></param>
		private void iterateFileCodeModel(FileCodeModel fileCode, TreeView filesTrv)
		{
			CodeElement codeElement = null; 
			TreeNode nameSpaceNode = null;
			int nameSpaceNodeIndex;

			for (int t = 1; t < fileCode.CodeElements.Count + 1; t++)
			{
				// Get code element
				codeElement = fileCode.CodeElements.Item(t);
				// Only process Namespace code types
				if (codeElement.Kind == vsCMElement.vsCMElementNamespace)
				{
					// Generate new namespace node if index 0 otherwise use existing node
					nameSpaceNodeIndex = NameSpaceNode(codeElement.FullName, filesTrv);
					if (nameSpaceNodeIndex == -1)
					{
						nameSpaceNode = filesTrv.Nodes.Add(codeElement.FullName);
						//Tag the code element to the node, to be used by HTML page generation.
						nameSpaceNode.Tag = codeElement;
					}
					else
						nameSpaceNode = filesTrv.Nodes[nameSpaceNodeIndex];
					foreach (CodeElement cdClassElmnt in ((CodeNamespace)codeElement).Members)
					{
						if(cdClassElmnt.Kind == vsCMElement.vsCMElementClass)
						{
							TreeNode classNode = nameSpaceNode.Nodes.Add(cdClassElmnt.Name);
							//Tag the class element to the node, to be used by HTML page generation.
							classNode.Tag = cdClassElmnt;
						}
					}
				}
			}
		}

		/// <summary>
		/// Searches tree view to determine if nameSpace exists, if so return node index otherwise retrn 0.
		/// </summary>
		/// <param name="nameSpace"></param>
		/// <param name="filesTrv"></param>
		/// <returns></returns>
		private int NameSpaceNode(string nameSpace, TreeView filesTrv)
		{
			int nodeIndex = -1;

			for (int i = 0; i < filesTrv.Nodes.Count; i++)
				if (filesTrv.Nodes[i].Text == nameSpace)
					nodeIndex = i;

			return nodeIndex;
		}
		#endregion

		#region HTML help page generation methods
		/// <summary>
		/// Write HTML Left page and associated HTML detail files
		/// </summary>
		/// <param name="filesTrv"></param>
		private void WriteHtmlLeftPage(TreeView filesTrv)
		{
			// create folders, directory and copy common files
			string htmlHelpPath = saveTbx.Text + "\\HtmlHelp";
			createDirAddFiles(htmlHelpPath);

			// Set up file streaming
			FileStream fs = new FileStream("leftpage.htm", FileMode.Create );
			StreamWriter sw = new StreamWriter(fs);  

			Console.SetOut(sw);
			sw.Write(HTMLHEADER, "htmlhelp leftframe", "");
			sw.Write(TAGHEAD);

			sw.Write(BODYSTART);
			sw.Write(SPACER20);
			WriteProjectNameSpace(filesTrv, sw);

			sw.Write(TAGBODY);
			sw.Write(TAGHTML);
			sw.Close();
			//open htmlHelp index page in VS .NET browser
			dteApplication.ExecuteCommand("View.URL", htmlHelpPath + "\\index.htm");
		}

		#region Create directories and load with htm and gif files
		/// <summary>
		/// Create folders, directory and copy common files
		/// </summary>
		/// <param name="htmlHelpPath"></param>
		private void createDirAddFiles(string htmlHelpPath)
		{
			// Create main directory if not existing already
			if (Directory.Exists(htmlHelpPath) != true)
				Directory.CreateDirectory(htmlHelpPath);

			// Create images directory if not existing already
			if (Directory.Exists(htmlHelpPath + "\\" + imageDir) != true)
				Directory.CreateDirectory(htmlHelpPath + "\\" + imageDir);

			// Create classes directory if not existing already
			if (Directory.Exists(htmlHelpPath + "\\" + classDir) != true)
				Directory.CreateDirectory(htmlHelpPath + "\\" + classDir);

			// Set the project directory, copy common files.
			Directory.SetCurrentDirectory(htmlHelpPath);
			copyCommonFiles(htmlHelpPath);
		}

		//get resource files from the assembly
		/// <summary>
		/// Copy html and gif files into main and sub directories
		/// </summary>
		/// <param name="htmlHelpPath"></param>
		private void copyCommonFiles(string htmlHelpPath)
		{	
			Assembly assembly = Assembly.GetExecutingAssembly();	

			copyImage(assembly, htmlHelpPath, "bar.gif");
			copyImage(assembly, htmlHelpPath, "barleft.gif");
			copyImage(assembly, htmlHelpPath, "barnecourt.gif");
			copyImage(assembly, htmlHelpPath, "bartop.gif");
			copyImage(assembly, htmlHelpPath, "minus.gif");
			copyImage(assembly, htmlHelpPath, "plus.gif");
			copyImage(assembly, htmlHelpPath, "spacer.gif");

			copyFile(assembly, htmlHelpPath, "index.htm");
			copyFile(assembly, htmlHelpPath, "mainpage.htm");
			copyFile(assembly, htmlHelpPath, "toppage.htm");
			copyFile(assembly, htmlHelpPath, "htmlhelp.css");
		}

		/// <summary>
		/// Copy name image file to path + splus specifieid sub directory
		/// </summary>
		/// <param name="assembly"></param>
		/// <param name="path"></param>
		/// <param name="name"></param>
		private void copyImage(Assembly assembly, string path, string name)
		{	
			string pathName = path + "\\" + imageDir + "\\" + name;
			if (File.Exists(pathName) == false)
			{
				Image img = Image.FromStream(assembly.GetManifestResourceStream(assembly.GetName().Name + "." + name));
				img.Save(pathName);
			}
		}

		/// <summary>
		/// Copy name htm file to path directory
		/// </summary>
		/// <param name="assembly"></param>
		/// <param name="path"></param>
		/// <param name="name"></param>
		private void copyFile(Assembly assembly, string path, string name)
		{
			string pathName = path + "\\" + name;
			if (File.Exists(pathName) == false)
			{
				StreamReader sr = new StreamReader(assembly.GetManifestResourceStream(assembly.GetName().Name + "." + name));
				FileStream fs = new FileStream(pathName, FileMode.Create);
				StreamWriter sw = new StreamWriter(fs);
				Console.SetOut(sw);
				sw.Write(sr.ReadToEnd());
				sw.Close();
			}
		}
		#endregion

		/// <summary>
		/// Iterates though each namespace for the selected project
		/// </summary>
		/// <param name="filesTrv"></param>
		/// <param name="sw"></param>
		private void WriteProjectNameSpace(TreeView filesTrv, StreamWriter sw)
		{
			TreeNodeCollection filesNodes = filesTrv.Nodes;
			foreach (TreeNode nameSpaceTreeNode in filesNodes)
			{
				sw.Write(NAMESPACEHDR);
				sw.Write(nameSpaceTreeNode.Text + "\n");
				sw.Write(TAGDIV);
				
				WriteProjectClass(nameSpaceTreeNode, sw);
			}
		}

		/// <summary>
		/// Iterates though each class for the selected project namespace
		/// </summary>
		/// <param name="nameSpaceTreeNode"></param>
		/// <param name="sw"></param>
		private void WriteProjectClass(TreeNode nameSpaceTreeNode, StreamWriter sw)
		{
			string classFileNameStr;

			sw.Write(NAMESPACECHILD);
			foreach (TreeNode classTreeNode in nameSpaceTreeNode.Nodes)
			{
				classFileNameStr = className + classCount + ".HTM";
				sw.Write(CLASSDEFINITION, classDir + "/" + classFileNameStr, classTreeNode.Text);
				WriteClassDetail(classTreeNode, classFileNameStr);
				classCount++;
			}
			sw.Write(TAGDIV);
		}

		/// <summary>
		/// Creates Class Description HTML page for the selected TreeNode
		/// </summary>
		/// <param name="classTreeNode"></param>
		/// <param name="classFileNameStr"></param>
		private void WriteClassDetail(TreeNode classTreeNode, string classFileNameStr)
		{
			string functionStr, summaryStr;	// Used to hold function and summary comments for class being processed

			CodeElement codeElement = (CodeElement)classTreeNode.Tag;
			CodeType codeType =(CodeType)codeElement;
			// Set up edit point
			EditPoint editPoint = codeType.GetStartPoint(vsCMPart.vsCMPartHeader).CreateEditPoint(); 

			string classTitle = classTreeNode.Parent.Text + "." + classTreeNode.Text;

			// Set up file streaming
			FileStream fs = new FileStream(classDir + "\\" + classFileNameStr, FileMode.Create );
			StreamWriter swc = new StreamWriter(fs);  

			Console.SetOut(swc);
			swc.Write(HTMLHEADER, classTitle, "../");
			swc.Write(TAGHEAD);

			swc.Write(BODYSTART);
			swc.Write(DESCRIPTION, classTitle, "Class");
			swc.Write(SIDEBARS, "../" + imageDir + "/", "../" + imageDir + "/");
			swc.Write(DIVREMARK);
			swc.Write(SPANREMARKTXT, "Access: ");
			
			// create Class Access line
			string classAccess;
			if (codeType.Access == vsCMAccess.vsCMAccessPublic)
				classAccess = "Public";
			else
				classAccess = "";
			swc.Write(classAccess);

			swc.Write(TAGDIV);
			swc.Write(DIVREMARK);

			// create Base Classes line
			if (codeType.Bases.Count != 0)
			{
				swc.Write(SPANREMARKTXT, "Base Classes: ");
				swc.Write(codeType.Bases.Item(1).Name);
			}
			else 
				swc.Write(SPANREMARKTXT, "");
			swc.Write(TAGDIV);

			// create Class Remarks line
			swc.Write(DIVREMARK);
			swc.Write(SPANREMARKTXT, "Remarks: ");
			swc.Write(SearchAndCut(codeType.DocComment, "<remarks>", "</remarks>"));
			swc.Write(TAGDIV);

			if (codeType.Members.Count !=0)
			{
				swc.Write(TABLEHEADER, "Members", "Detail");
			
				// Iterate through each of the classes functions
				for (int i = 0; i < codeType.Members.Count; i++)
				{
					codeElement = codeType.Members.Item(i+1);
					if (codeElement.Kind == vsCMElement.vsCMElementFunction) 
					{
						CodeFunction codeFunction = (CodeFunction)codeElement;
						// Move edit point to function definition
						editPoint.MoveToPoint(codeFunction.GetStartPoint(vsCMPart.vsCMPartHeader));

						// Get function method statement
						functionStr = editPoint.GetLines(editPoint.Line, editPoint.Line+1);
						// Get summary statement
						summaryStr = SearchAndCut(codeFunction.DocComment, "<summary>", "</summary>");

						Console.SetOut(swc);
						swc.Write(TABLEROW);
						swc.Write(TABLEWIDTH);
						swc.Write(TABLEINPUTSPACE);
						swc.Write(TABLEINPUTTOP, codeFunction.Name);
						swc.Write(TABLEINPUTFUN, functionStr, summaryStr);
						swc.Write(TABLEWIDTH);
						swc.Write(TAGTR);
					}
				}
				swc.Write(TAGTABLE);
			}
			swc.Write(TAGBODY);
			swc.Write(TAGHTML);
			swc.Close();
		}

		/// <summary>
		/// Used to find and extract a string from searchStr which is enclosed by the startStr and endStr strings.
		/// </summary>
		/// <param name="searchStr"></param>
		/// <param name="startStr"></param>
		/// <param name="endStr"></param>
		/// <returns></returns>
		private string SearchAndCut(string searchStr, string startStr, string endStr)
		{
			int startIndex=0, endIndex=0;
			string[] searchStrArray, temp;
			string returnStr = "", tmp;

			// Seperate the search string
			searchStrArray = searchStr.Split("\n".ToCharArray());
			if ((searchStr.IndexOf(startStr) > -1) && (searchStr.IndexOf(endStr) > -1))
			{
				// Search for start and end strings
				for (int j = 0; j < searchStrArray.Length; j++)
				{
					if (searchStrArray[j].IndexOf(startStr) > -1)
						startIndex = j;
					if (searchStrArray[j].IndexOf(endStr) > -1)
						endIndex = j;
				}
				// Extract string based on start and end index
				while (endIndex > startIndex+1)
				{	
					temp = searchStrArray[endIndex-1].Split("'///".ToCharArray());
					tmp = temp[temp.Length-1];
					returnStr = returnStr.Insert(0, tmp);
					endIndex --;
				}
			}
			return returnStr;
		}
		#endregion

		#region HTML web page constants
		// Constants used to generate the HTML web pages
		const string	HTMLHEADER  = "<HTML>\n"
			+ "<HEAD>\n"
			+ "<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"
			+ "<TITLE>{0}</TITLE>\n"
			+ "<LINK REL=STYLESHEET HREF=\"{1}htmlhelp.css\" TYPE=\"text/css\">\n";
		const string	TAGHEAD = "</HEAD>\n";
		const string	BODYSTART = "<BODY>\n";
		const string	TAGBODY = "</BODY>\n";
		const string	TAGHTML = "</HTML>\n";

		const string	SPACER20 = "<img src=\"images/spacer.gif\" height=\"20\">\n";
		const string	NAMESPACEHDR = "<DIV CLASS=\"Namespace\">\n"
			+ "<IMG src=\"images/plus.gif\">\n";
		const string	TAGDIV = "</DIV>\n";

		const string	NAMESPACECHILD = "<DIV CLASS=\"NamespaceChild\" style=\"display:block; position:relative; left:35px;\">\n";
		const string	CLASSDEFINITION = "<DIV><A HREF=\"{0}\" TARGET=\"mainframe\">{1}</A></DIV>\n";

		const string	DESCRIPTION = "<DIV CLASS=\"PageHeading\">{0} {1}</DIV>\n"
			+ "<DIV CLASS=\"Description\">\n"
			+ "</DIV>\n";
		const string	SIDEBARS = "<IMG src=\"{0}barleft.gif\" width=7 height=378 alt=\"\" border=\"0\" style=\"position:absolute; left:10; top:18;z-Index:2\">\n"
			+ "<IMG src=\"{1}bartop.gif\" width=352 height=7 alt=\"\" border=\"0\" align=\"top\" style=\"position:absolute; left:10; top:18; z-index:1\">\n";
		const string	DIVREMARK = "<DIV CLASS=\"Remarks\">\n";
		const string	SPANREMARKTXT = "<SPAN CLASS=\"RemarkText\">{0}</SPAN>";

		const string	TABLEHEADER = "<TABLE CLASS=\"Table\" cellpadding=0 cellspacing=0>\n"
			+ "<TR>\n"
			+ "<TD height=20 width=20>&nbsp;</TD>\n"
			+ "<TD CLASS=\"TableDarkGreen\" width=10>&nbsp;</TD>\n"
			+ "<TD CLASS=\"TableDarkGreen\" width=200>{0}</TD>\n"
			+ "<TD CLASS=\"TableDarkGreen\">{1}</TD>\n"
			+ "<TD width=20>&nbsp;</TD>\n"
			+ "</TR>\n";
		const string	TABLEROW = "<TR>\n";
		const string	TABLEWIDTH = "<TD height=20 width=20>&nbsp;</TD>\n";
		const string	TABLEINPUTSPACE = "<TD CLASS=\"TableLightGreen\">&nbsp;</TD>\n";
		const string	TABLEINPUTTOP = "<TD valign=\"top\" CLASS=\"TableLightGreen\">{0}</TD>\n";
		const string	TABLEINPUTFUN = "<TD CLASS=\"TableLightGreen\"><strong>{0}</strong><br>{1}<br></TD>\n";
		const string	TAGTR = "</TR>\n";
		const string	TAGTABLE = "</TABLE>\n";
		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United Kingdom United Kingdom
Mike Knuckey is a software consultant for Barnecourt Solutions, operating from Dartmoor, Devon, UK.

Comments and Discussions