前一段時間應公司要求,讓我開發一個數據庫字段信息CHM幫助文件生成軟件。結果當時我就二了,這個東西我只用過,不知道咋做啊。沒想到老大很隨意說一句:"沒事,這個軟件我之前有有源碼,只不過現在不能用了,你等會參考一下就可以了"。我當時還傻乎乎的謝天謝地,總算有源碼可以參考了。當源代碼發過來以后,我頓時石化了,我。。。。。,那玩意兒用c++builder開發的,硬着頭皮看了一遍,全是帶*指針變量、數組、集合、函數,更要命的是,一個類里面寫了四五千行沒注視的代碼,函數中五六百行代碼的有幾個。 我說這不是坑人嘛?結果看了一天后,我果斷放棄看了那個源碼了,最后還是的感謝網上活躍的一幫朋友,在一個源碼的幫助下(源碼我不知道怎么上傳,),終於完成了任務啊,
吐槽到此為止,言歸正傳,首先如下:
生成事件

1 /// <summary> 2 /// 生成 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 private void button1_Click(object sender, EventArgs e) 7 { 8 try 9 { 10 if (!Directory.Exists("HTML")) //判斷名為HTML文件夾是否存在,不存在的話就創建一個 11 { 12 Directory.CreateDirectory("HTML"); 13 } 14 startPath = Application.StartupPath;//起始路徑 15 OpenHhp(_defaultTopic);//打開hhp文件 16 OpenHhc(_defaultTopic);//打開hhc文件 17 OpenHhk();//打開hhk文件 18 Compile(); 19 MessageBox.Show("生成成功!"); 20 } 21 catch (Exception ex) 22 { 23 MessageBox.Show("生成失敗!"); 24 throw; 25 } 26 27 }
從方法中我可以看出,我們需要一個hhp文件,hhc文件,hhk文件,然后再執行compile方法就可以了
首先動態生一個hhp,代碼如下:
1 /// <summary> 2 /// 創建hhp文件 3 /// </summary> 4 /// <param name="htmFile">htm文件名</param> 5 public void OpenHhp(string htmFile) 6 { 7 FileStream fs = new FileStream("test.hhp", FileMode.Create); //創建hhp文件 8 streamWriter = new System.IO.StreamWriter(fs, System.Text.Encoding.GetEncoding("GB18030")); 9 10 11 streamWriter.WriteLine("[OPTIONS]"); 12 streamWriter.WriteLine("Compatibility=1.1 or later"); 13 streamWriter.WriteLine("Compiled file=" + textBox1 .Text.Trim()+ ".chm"); //定義生成文件名稱 14 streamWriter.WriteLine("Contents file=test.hhc"); 15 streamWriter.WriteLine("Default topic=HTML\\全部對象.htm"); 16 streamWriter.WriteLine("Display compile progress=Yes"); 17 streamWriter.WriteLine("Index file=DBO_HELP.hhk"); 18 streamWriter.WriteLine("Language=0x804 中文(中國)"); 19 streamWriter.WriteLine("Title=數據庫結構展示"); 20 streamWriter.WriteLine(" "); 21 streamWriter.WriteLine("[FILES]"); 22 streamWriter.WriteLine("全部對象.htm"); 23 streamWriter.WriteLine(" "); 24 streamWriter.WriteLine("[INFOTYPES]"); 25 streamWriter.WriteLine(htmFile); 26 streamWriter.WriteLine(); 27 streamWriter.Close(); 28 }
這樣在項目的根目錄上面就生成了一個hhp文件
現在就要生成hhc文件了,它主要就是生成chm文件左邊顯示樹形的內容,當點擊節點,可以超鏈接要顯示的頁面(其實CHM中的內容都是HTML,你可以直接連接靜態網頁,),當然是顯示在右邊,而我的項目中要顯示東西都是動態生成HTML文件,所以這個生成有些復雜,不過我這里會截取主要部分代碼講解:
private void OpenHhc(string htmFile) { StringBuilder Modes = new StringBuilder(); FileStream fs = new FileStream(GetContentsHtmlFilename(), FileMode.Create); //創建hhp文件 streamWriter = new System.IO.StreamWriter(fs, System.Text.Encoding.GetEncoding("GB18030")); FileStream fs1 = new FileStream("HTML\\全部對象.htm", FileMode.Create); // str1 = new System.IO.StreamWriter(fs1, System.Text.Encoding.GetEncoding("GB18030")); streamWriter.WriteLine("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">"); streamWriter.WriteLine("<HTML>"); streamWriter.WriteLine("<HEAD>"); streamWriter.WriteLine("<meta name=\"GENERATOR\" content=\"Microsoft® HTML Help Workshop 4.1\">"); streamWriter.WriteLine("<!-- Sitemap 1.0 -->"); streamWriter.WriteLine("</HEAD>"); streamWriter.WriteLine("<BODY>"); streamWriter.WriteLine("<OBJECT type=\"text/site properties\">"); streamWriter.WriteLine("<param name=\"Window Styles\" value=\"0x800025\">"); streamWriter.WriteLine("</OBJECT>"); string sql = "SELECT mId,mName FROM Models"; DataTable dt = DBHelper.getDatatable(sql); for (int i = 0; i < dt.Rows.Count; i++) { #region if (i == 0) { streamWriter.WriteLine(" <UL>"); streamWriter.WriteLine(" <LI> <OBJECT type=\"text/sitemap\">"); streamWriter.WriteLine(" <param name=\"Name\" value=\"數據庫服務器\">"); streamWriter.WriteLine(" <param name=\"Local\" value=\"HTML\\全部對象.htm\">"); streamWriter.WriteLine(" <param name=\"ImageNumber\" value=\"13\">"); streamWriter.WriteLine(" </OBJECT>"); streamWriter.WriteLine(" <UL>"); Modes.Append("<!doctype html public \"-//W3C//DTD HTML 4.0 Transitional//EN\"> \r"); Modes.Append("<html> \r"); Modes.Append(" <head> \r"); Modes.Append(" <title>所有模塊</title> \r"); Modes.Append(" <meta name=\"Generator\" content=\"EditPlus\"> \r"); Modes.Append(" <meta name=\"Author\" content=\"\"> \r"); Modes.Append(" <meta name=\"Keywords\" content=\"\"> \r"); Modes.Append(" <meta name=\"Description\" content=\"\"> \r"); Modes.Append(" </head> \r"); Modes.Append(" <body> \r"); Modes.Append(" <div align=\"Center\" style=\"font-size:20px;font-width:bold;;color:green\">全部模塊</div>\r"); Modes.Append(" <hr color = #FF0000>"); Modes.Append(" <div align=\"Center\"><A href=\""+dt.Rows[i]["mName"].ToString()+".htm\">"+dt.Rows[i]["mName"].ToString()+"</A></div>\r"); } if (i > 0) { Modes.Append(" <br/>"); Modes.Append(" <div align=\"Center\"><A href=\"" + dt.Rows[i]["mName"].ToString() + ".htm\">"+dt.Rows[i]["mName"].ToString()+"</A></div>\r"); } streamWriter.WriteLine(" <LI> <OBJECT type=\"text/sitemap\">"); streamWriter.WriteLine(" <param name=\"Name\" value=\"" + dt.Rows[i]["mName"].ToString() + "\">"); streamWriter.WriteLine(" <param name=\"Local\" value=\"HTML\\" + dt.Rows[i]["mName"].ToString() + ".htm\">"); streamWriter.WriteLine(" <param name=\"ImageNumber\" value=\"21\">"); //streamWriter.WriteLine(" <param name=\"ImageNumber\" value=\"1\">"); streamWriter.WriteLine(" </OBJECT>"); streamWriter.WriteLine("</UL>"); Modes.Append(" </BODY>\r</HTML>"); } streamWriter.WriteLine("</UL>\r</UL>\r</BODY>\r</HTML>"); streamWriter.WriteLine(); streamWriter.Close(); str1.WriteLine(Modes); str1.Close(); } }
這語法很像HTML,但同時也不是,<UL></UL>代表一級節點,其中中間的 " <LI> <OBJECT type=\"text/sitemap\"><param name=\"Name\" value=\"數據庫服務器\"><param name=\"Local\" value=\"HTML\\全部對象.htm\"><param name=\"ImageNumber\" value=\"13\"></OBJECT>"這段代碼負責節點內容、連接、圖片顯示功能,如果<UL>內容嵌套的話,則表示下一級節點。還有我定義的modes,它主要負責生成一個Htm文件(記住用文件流生成,文件后綴名不要用html,而要用htm,不然會有錯誤,具體我也不知道啥原因),這樣hhc文件生成在根目錄下
接下來,則要生成hhk文件了
它主要負責你索引部分要顯示的內容,這里生成也很簡單
1 private void OpenHhk() 2 { 3 FileStream fs = new FileStream(startPath + @"\test.hhk", FileMode.Create); //創建hhp文件 4 //streamWriter = new System.IO.StreamWriter(fs, System.Text.Encoding.GetEncoding("GB18030")); 5 streamWriter = new System.IO.StreamWriter(fs, System.Text.Encoding.GetEncoding("UTF-8")); 6 streamWriter.WriteLine("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">"); 7 streamWriter.WriteLine("<HTML>"); 8 streamWriter.WriteLine("<HEAD>"); 9 streamWriter.WriteLine("<meta name=\"GENERATOR\" content=\"Microsoft® HTML Help Workshop 4.1\">"); 10 streamWriter.WriteLine("<!-- Sitemap 1.0 -->"); 11 streamWriter.WriteLine("</HEAD>"); 12 streamWriter.WriteLine("<BODY>"); 13 streamWriter.WriteLine("<UL>"); 14 string sql = "SELECT dId,dName,status,dCreTime,dFieidNum,dChName,dFunctionDesc FROM Documents order by dName"; 15 //string sqls = ""; 16 DataTable dt1 = DBHelper.getDatatable(sql); 17 foreach (DataRow dr in dt1.Rows) 18 { 19 streamWriter.WriteLine(" <LI> <OBJECT type=\"text/sitemap\">"); 20 streamWriter.WriteLine(" <param name=\"Name\" value=\"" + dr["dName"].ToString() + "\">"); 21 streamWriter.WriteLine("<param name=\"Local\" value=\"" + dr["dName"].ToString() + ".htm\">"); 22 streamWriter.WriteLine("</OBJECT>"); 23 } 24 streamWriter.WriteLine("</UL>"); 25 streamWriter.WriteLine("</BODY>"); 26 streamWriter.WriteLine("</HTML>"); 27 streamWriter.WriteLine(); 28 streamWriter.Close(); 29 }
執行以后就可以在根目錄下生成hhk文件了
到此為止,生成chm文件的必須的三大文件已經搞定了,下面就是compile方法了
1 string hhcFile = @"C:\Program Files\HTML Help Workshop\hhc.exe";//hhc.exe文件位置,windows自帶的,一般是這個路徑 2 public string _defaultTopic = "";//默認的頁面 3 private bool Compile() 4 { 5 string _chmFile = startPath + @"\test.chm";//chm文件存儲路徑 6 Process helpCompileProcess = new Process(); //創建新的進程,用Process啟動HHC.EXE來Compile一個CHM文件 7 try 8 { 9 //判斷文件是否存在並不被占用 10 try 11 { 12 string path = _chmFile; //chm生成路徑 13 if (File.Exists(path)) 14 { 15 File.Delete(path); 16 } 17 } 18 catch(Exception e) 19 { 20 throw new Exception("文件被打開!"); 21 } 22 23 ProcessStartInfo processStartInfo = new ProcessStartInfo(); 24 processStartInfo.WindowStyle = ProcessWindowStyle.Hidden; 25 processStartInfo.FileName = hhcFile; //調入HHC.EXE文件 26 processStartInfo.Arguments = "\"" + GetPathToProjectFile() + "\"";//獲取空的HHP文件 27 processStartInfo.UseShellExecute = false; 28 helpCompileProcess.StartInfo = processStartInfo; 29 helpCompileProcess.Start(); 30 helpCompileProcess.WaitForExit(); //組件無限期地等待關聯進程退出 31 32 if (helpCompileProcess.ExitCode == 0) 33 { 34 MessageBox.Show(new Exception().Message); 35 return false; 36 } 37 } 38 finally 39 { 40 helpCompileProcess.Close(); 41 } 42 return true; 43 }
滿足上面三個文件要求,再執行這個方法,一個CHM幫助文件就可以生成,
其實網上有很多生成chm文件的工具,但我從沒用過,還好目前我這個用着還可以湊合,而且顯示的樣式可以自己修改成自己喜歡的那種(考你樣式了,)秀秀我的作品(悲催啊,不知道咋吧程序上傳上來,希望有知道的告訴一下),寫起來感覺有點吃力,不好勿噴