在这篇文章中,我将介绍AlexisEditor项目下主要Form的实现,即MainForm、EditForm。

MainForm 

MainForm包含的主要变量如下 

 

以frm开头的都是对应的窗体变量,chmDocument表示当前的电子书,dockPanel是MainForm上的Panel,负责实现Visual Studio风格的面板。

下图是MainForm的主要方法。

 

在一开始是实例化Form窗体的时候会调自身的构造器,在构造器中我们其他的窗体,主要代码如下

 
  
  1. frmIndex.Show(dockPanel);//显示目录窗体  
  2.  frmIndex.DockTo(dockPanel, DockStyle.Left);  
  3.  frmList.Show(dockPanel);//显示搜索窗体  
  4.  frmList.DockTo(dockPanel, DockStyle.Fill);  
  5.  this.frmIndex.TreeIndex.NodeMouseDoubleClick += new TreeNodeMouseClickEventHandler(TreeIndex_NodeMouseDoubleClick);//注册编辑文章事件  

加载界面的时候会触发MainForm_Load事件,我们在这个方法里面加载电子书的目录,代码如下:

 
  
  1. chmDocument.Load("index.xml");//加载目录  
  2.  RefreshView(chmDocument, frmIndex.TreeIndex);  

RefreshView是同步TreeView和CHMDocument的方法,很重要

 
  
  1. private void RefreshView(CHMDocument doc, System.Windows.Forms.TreeView tvw)  
  2. {  
  3.             tvw.BeginUpdate();  
  4.             tvw.Nodes.Clear();  
  5.             System.Windows.Forms.TreeNode node = tvw.Nodes.Add(doc.Title);  
  6.             node.Tag = doc;  
  7.             node.ImageIndex = 0;  
  8.             node.SelectedImageIndex = 0;  
  9.             AddNodes(doc.Nodes, node);  
  10.             tvw.EndUpdate();  
  11.             tvw.SelectedNode = node;  
  12.             node.Expand();  
  13.  
  14.  }  

RefreshView会调用AddNodes方法添加节点,方法明细如下

 
  
  1. private void AddNodes(CHMNodeList list, System.Windows.Forms.TreeNode RootNode)  
  2. {  
  3.             if (list == null || list.Count == 0)  
  4.                 return;  
  5.  
  6.             foreach (CHMNode node in list)  
  7.             {  
  8.                 System.Windows.Forms.TreeNode n = new TreeNode(node.Name);  
  9.                 n.Tag = node;  
  10.                 if (node.Nodes.Count > 0)  
  11.                     n.ImageIndex = 0;  
  12.                 else  
  13.                     n.ImageIndex = 1;  
  14.                 nn.SelectedImageIndex = n.ImageIndex;  
  15.                 RootNode.Nodes.Add(n);  
  16.                 if (node.Nodes.Count > 0)  
  17.                     AddNodes(node.Nodes, n);  
  18.             }  

New方法是新建文章方法,当我们选中目录节点,右击的时候会出现一些菜单,其中就有新建文章

方法体很简单,其他的事情都交给EditForm去完成

 
  
  1. EditForm frmEdit = EditForm.CreateEditForm();                  
  2.  
  3. frmEdit.Show(); 

Compile方法是编译方法,负责将目录中的文章编译为对应的CHM电子书,并且在编译的时候主页面下方的状态栏会显示编译过程,虽然是比较简陋的编译过程。

 
  
  1. //编译方法  
  2. private void Compile()  
  3. {  
  4.             frmOutPut.Show(dockPanel);  
  5.             frmOutPut.DockTo(dockPanel, DockStyle.Bottom);  
  6.             chmDocument.FileName = "index.xml";  
  7.             chmDocument.Compile();  
  8.             //frmOutPut.RtbOutput.Text = chmDocument.OutPutText;  
  9.             frmOutPut.TxtOutput.Text = chmDocument.OutPutText;  
  10. }  

AddPage对应着程序工具栏上的IE图标,添加HMTL页面的功能,主要代码如下:

 
  
  1. //添加页面,此处只是将路径存入,并没有将文件考到相应的路径下(可用性待分析)  
  2.         private void AddPage()  
  3.         {  
  4.             TreeNode node = this.frmIndex.TreeIndex.SelectedNode;//选中的节点  
  5.             //查看是否是根节点或是目录节点  
  6.             CHMNodeList list = this.GetNodeList(node);  
  7.             if (list == null)  
  8.             {  
  9.                 MessageBox.Show("请选择根节点或是目录节点");  
  10.                 return;  
  11.             }  
  12.             using (OpenFileDialog ofd = new OpenFileDialog())//可以批量选择  
  13.             {  
  14.                 ofd.Filter = "HTML Files|*.html;*.htm";  
  15.                 ofd.Multiselect = true;//设置可以选择多个文件  
  16.                 ofd.ShowDialog();  
  17.                   
  18.                   
  19.                 if (ofd.FileNames.Length > 0)  
  20.                 {  
  21.                     for (int i = 0; i < ofd.FileNames.Length; i++)  
  22.                     {  
  23.                         CHMNode newnewNode = new CHMNode();//创建新的节点  
  24.                         newNode.Name = ofd.SafeFileNames[i].ToString();  
  25.                         newNode.ImageNo = "1";                          
  26.                         newNode.Local = ofd.FileNames[i].ToString();  
  27.                         newNode.Nodes = null;  
  28.                         list.Add(newNode);  
  29.                         System.Windows.Forms.TreeNode node2 = new TreeNode(newNode.Name);  
  30.                         node2.Tag = newNode;  
  31.                         node2.ImageIndex = 1;  
  32.                         node2.SelectedImageIndex = 1;  
  33.                         node.Nodes.Add(node2);//将新节点添加到树中  
  34.                         node.ImageIndex = 0;  
  35.                         node.SelectedImageIndex = 0;  
  36.                     }  
  37.                 }  
  38.             }  
  39.         } 

 

保存方法是将目录上的信息保存到xml 文件中,是调用CHMDocument类中的Save方法。
 

 
  
  1. //保存方法  
  2.  private void Save()  
  3. {  
  4.             chmDocument.Save("index.xml");  

EditForm窗体

startPath:程序的开始路径,有重要用处

node属性:负责和其他页面的交互

wbEditor:WebBrowser控件的实例,负责加载HTML编辑器,保存文章等功能
 

txtName:文章的标题

txtKeyWords:文章的关键字,用于Lucene.NET搜索

下面来看看他的一些主要方法及其实现:

 

EditForm_Load方法:加载编辑器,实现如下:

 
  
  1. /// <summary> 
  2.         /// 窗体加载事件  
  3.         /// </summary> 
  4.         /// <param name="sender"></param> 
  5.         /// <param name="e"></param> 
  6.         private void EditForm_Load(object sender, EventArgs e)  
  7.         {  
  8.             startPath = Application.StartupPath;//起始路径  
  9.             //这边可以做成从配置文件中读取选择什么编辑器  
  10.             //Uri u = new Uri(startPath + @"\ckeditor\index.html");  
  11.             this.wbEditor.Navigating += new WebBrowserNavigatingEventHandler(wbEditor_Navigating);//为了获取前台的点击事件  
  12.             Uri u = new Uri(startPath + @"\CSDN_UBB\normal.htm");  
  13.             this.wbEditor.Url = u;  
  14.         }  

WebBrowser控件中的html事件,是通过Navigating方法来实现的,WebBrowser导航发生改变时就会触发如下的方法,我们可以自己写js事件,让WebBrowser的导航发生改变

如这边

 
  
  1. <script type="text/javascript"> 
  2.         function getValue(){  
  3.             document.getElementById("content").value=document.getElementById("tb_ReplyBody___Editor").innerHTML;  
  4.             this.location.href="loading.htm";  
  5.         }  
  6.         </script> 

具体的实现可以参考源代码

 

 
  
  1. void wbEditor_Navigating(object sender, WebBrowserNavigatingEventArgs e)  
  2.         {  
  3.             if (e.Url.AbsolutePath.ToString().Replace('/', '\\') == startPath + @"\CSDN_UBB\loading.htm")  
  4.             {  
  5.                 HtmlDocument hd = this.wbEditor.Document;//获取文档信息  
  6.                 HtmlElement he = hd.GetElementById("content");  
  7.                 IHTMLDocument2 doc = (IHTMLDocument2)this.wbEditor.Document.DomDocument;  
  8.                 mshtml.HTMLInputElement text1 = (HTMLInputElement)doc.all.item("content");//获取隐藏域中的值  
  9.                 string rr = text1.value;  
  10.                 if (this.txtName.Text == "")  
  11.                 {  
  12.                     MessageBox.Show("文章标题不能为空!");  
  13.                     return;  
  14.                 }  
  15.  
  16.                 string filename = GetFileName();  
  17.                 if (filePathEdit != "")  
  18.                 {  
  19.                     filename = filePathEdit.Substring(filePathEdit.LastIndexOf('\\') + 1);  
  20.                     filenamefilename = filename.Substring(0, filename.LastIndexOf('.'));  
  21.                     File.Delete(filePathEdit);  
  22.                 }  
  23.                 //将内容存入到html模板中,并生产html文件  
  24.                 if (rr != "")  
  25.                 {  
  26.                     FileStream fs = new FileStream("html_files\\" + filename + ".htm", FileMode.Create);//文件名  
  27.                     StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.GetEncoding("UTF-8"));  
  28.                     sw.WriteLine("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");  
  29.                     sw.WriteLine("<html xmlns=\"http://www.w3.org/1999/xhtml\">");  
  30.                     sw.WriteLine("<head>");  
  31.                     sw.WriteLine("<title>" + this.txtName.Text + "</title>");//文章名  
  32.                     sw.WriteLine("<meta content=\"text/html; charset=utf-8\" http-equiv=\"content-type\"/>");  
  33.                     sw.WriteLine("<link type=\"text/css\" rel=\"stylesheet\" href=\"Styles/SyntaxHighlighter.css\"></link>");  
  34.                     sw.WriteLine("<script type=\"text/javascript\" src=\"Scripts/shCore.js\"></script>");  
  35.                     sw.WriteLine("<script type=\"text/javascript\" src=\"Scripts/shBrushCSharp.js\"></script>");  
  36.                     sw.WriteLine("<script type=\"text/javascript\" src=\"Scripts/shBrushXml.js\"></script>");  
  37.                     sw.WriteLine("<script type=\"text/javascript\"> window.onload = function () {");  
  38.                     sw.WriteLine("dp.SyntaxHighlighter.ClipboardSwf = 'Scripts/clipboard.swf';");  
  39.                     sw.WriteLine("dp.SyntaxHighlighter.HighlightAll('code');}");  
  40.                     sw.WriteLine("</script>");  
  41.                     sw.WriteLine("</head>");  
  42.                     sw.WriteLine("<body>");  
  43.                     rr = ChangeString(rr);  
  44.                     sw.WriteLine(rr);  
  45.                     sw.WriteLine("</body>");  
  46.                     sw.WriteLine("</html>");  
  47.                     sw.Close();  
  48.                 }  
  49.                 //将节点返回给目录,暂不做保存操作  
  50.                 node = new CHMNode();  
  51.                 node.Local = startPath + "\\html_files\\" + filename + ".htm";  
  52.                 node.Name = this.txtName.Text;  
  53.                 node.Nodes = null;  
  54.                 node.ImageNo = "1";  
  55.  
  56.                 //TODO: 使用Lucene.Net存储索引,方便以后的搜索  
  57.  
  58.                 this.Close();  
  59.                 //this.wbEditor.Url = new Uri(startPath + @"\success.htm");  
  60.             }  
  61.         }  
  62.         #endregion 

ok,至此,主要的部分都已经讲解了(还有一个BookIndexForm,在下篇中和其他的一起讲解),还有许多细节的地方可参考我的源代码

 源代码下载(简陋版)

PS:不是最新版的源代码,最新版的源代码还在开发中, 恕不提供,嘿嘿