C#生成CHM文件(应用篇)之代码库编辑器(4)【附程序最终版下载】
2010-10-23 18:24
579 查看
呵呵,程序终于告一段落了,程序也终于Finish了,让大家久等了,希望不会让大家失望。
这也是比较典型的WinForm项目了,想学习WinForm开发的朋友可以照着我的步骤做下去,而且也提供了初版的源代码。
虽然项目比较小,而且几乎没涉及到什么业务上的东西,不过程序开发涉及面很大,有:
1.文件操作(包括文件的写,读取等)
2.XML操作(将字符写入XML中和读取XML、利用XML做配置文件等)
3.递归算法(树)【虽然在实际中用的不多,还是希望大家能够掌握】
4.TreeView、DataGridView、WebBrowser、OpenFileDialog等典型的WinForm控件
5.WinForm中切割图片、图片拼合、读取资源文件中的资源
....
因为是比较小的程序就没有分层,不过程序中也用到了不同一般WinForm项目的思想,具体体现在MainForm和其他Form的关系(详细可以参考源代码)
Ok ,看下程序的界面,和开始有一点变化。下面看看程序的截图吧,程序下载在最下面
主界面(去掉了以前没有的菜单里,只剩工具栏)
编译界面(有简陋的正在编译效果)
配置页面(为了简单起见,还是默认Csdn编辑器,如果有兴趣的话,你们自己可以结合以前给的源代码加入新的编辑器)
添加文件界面(可以批量导入)
最终生成的CHM电子书界面
今天的主要内容是目录窗体的实现及搜索的实现
目录窗体BookIndexForm
目录窗体中,有一个ContextMenuSTrip,即右击窗体出现的菜单,里面有几个比较重要的方法
添加文件夹、添加文章、删除、重命名
添加文件夹即添加父节点, 选中可以添加文件夹的节点(显然只有根节点和目录节点),然后将新增一个CHMNode,将它Add到父节点的Nodes里面
添加文章即添加 子节点,注意这时添加的节点他的Nodes要设为null,表示他是文章节点,不能再添加其他节点了
重命名:右击节点可以编辑节点的Label,
实现方法如下:
将TreeView的LabelEdit设为True,然后编写如下代码:
删除节点,即移除,同时还要删除文件
代码库搜索功能(Lucene.Net 2.0.04)
这个搜索只是简单的使用Lucene.Net实现的搜索。
我们在点击搜索按钮的时候,才开始做索引的操作。遍历chmDocument这个类,将节点信息存储为索引,然后查的时候就去查索引,好像有点多此一举。
其实不然,因为我们要全文模糊检索,我们不能看将每个文件打开,然后找找里面有没有这个搜索词。所以就用Lucene.Net。
具体实现代码如下:
其中,写入索引的代码如下,也是使用遍历的(一开始想当然地做了,结果老是死循环,看来递归还是没有掌握好)
在搜索界面中还是用了TabControl,以前用过DevExpress的TabControl,它隐藏 TabControl标签有现成的方法的,但是MS的TabControl貌似没有这个方法,于是就弄了讨巧的方法,将TabControl放在一个Panel中,头部稍微超出Panel的边界,然后在Form_Load方法中写如下代码:
附件下载 AlexisEditor RC版
说明:如果没有重大bug或者是反馈了,这个系列就到这边结束了,后面有篇文章专门总结这一系列的,里面的知识点还是比较多的,希望里面的知识能够帮到大家。
附件:http://down.51cto.com/data/2358207
这也是比较典型的WinForm项目了,想学习WinForm开发的朋友可以照着我的步骤做下去,而且也提供了初版的源代码。
虽然项目比较小,而且几乎没涉及到什么业务上的东西,不过程序开发涉及面很大,有:
1.文件操作(包括文件的写,读取等)
2.XML操作(将字符写入XML中和读取XML、利用XML做配置文件等)
3.递归算法(树)【虽然在实际中用的不多,还是希望大家能够掌握】
4.TreeView、DataGridView、WebBrowser、OpenFileDialog等典型的WinForm控件
5.WinForm中切割图片、图片拼合、读取资源文件中的资源
....
因为是比较小的程序就没有分层,不过程序中也用到了不同一般WinForm项目的思想,具体体现在MainForm和其他Form的关系(详细可以参考源代码)
Ok ,看下程序的界面,和开始有一点变化。下面看看程序的截图吧,程序下载在最下面
主界面(去掉了以前没有的菜单里,只剩工具栏)
编译界面(有简陋的正在编译效果)
配置页面(为了简单起见,还是默认Csdn编辑器,如果有兴趣的话,你们自己可以结合以前给的源代码加入新的编辑器)
添加文件界面(可以批量导入)
最终生成的CHM电子书界面
今天的主要内容是目录窗体的实现及搜索的实现
目录窗体BookIndexForm
目录窗体中,有一个ContextMenuSTrip,即右击窗体出现的菜单,里面有几个比较重要的方法
添加文件夹、添加文章、删除、重命名
添加文件夹即添加父节点, 选中可以添加文件夹的节点(显然只有根节点和目录节点),然后将新增一个CHMNode,将它Add到父节点的Nodes里面
/// <summary> /// 添加文件夹 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void AddFolderToolStripMenuItem_Click(object sender, EventArgs e) { TreeNode node = this.tvIndex.SelectedNode;//选中的节点 //查看是否是根节点或是目录节点 CHMNodeList list = this.GetNodeList(node); if (list == null || list.Count==0) { MessageBox.Show("请选择根节点或是目录节点"); return; } //创建新的节点 CHMNode newnewNode = new CHMNode(); newNode.Name = "新建文件夹"; newNode.ImageNo = "0"; //newnewNode.Nodes = new CHMNodeList(); list.Add(newNode); System.Windows.Forms.TreeNode node2 = new TreeNode(newNode.Name); node2.Tag = newNode; node2.ImageIndex = 0; node2.SelectedImageIndex = 0; node.Nodes.Add(node2);//将新节点添加到树中 node.ImageIndex = 0; node.SelectedImageIndex = 0; this.tvIndex.SelectedNode = node2; }
添加文章即添加 子节点,注意这时添加的节点他的Nodes要设为null,表示他是文章节点,不能再添加其他节点了
/// <summary> /// 添加文章 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void AddArticleToolStripMenuItem_Click(object sender, EventArgs e) { TreeNode node = this.tvIndex.SelectedNode; CHMNodeList list = this.GetNodeList(node); if (list == null) { MessageBox.Show("请选择根节点或是目录节点"); return; } EditForm frmEdit = new EditForm(); frmEdit.ShowDialog(this); CHMNode NewNode = frmEdit.Node; if(NewNode==null) { return; } list.Add(NewNode); System.Windows.Forms.TreeNode node2 = new TreeNode(NewNode.Name); node2.Tag = NewNode; node2.ImageIndex = 1; node2.SelectedImageIndex = 1; node.Nodes.Add(node2);//将新节点添加到树中 node.ImageIndex = 0; node.SelectedImageIndex = 0; this.tvIndex.SelectedNode = node2; }
重命名:右击节点可以编辑节点的Label,
实现方法如下:
将TreeView的LabelEdit设为True,然后编写如下代码:
private void ReNameMToolStripMenuItem_Click(object sender, EventArgs e) { this.tvIndex.SelectedNode.BeginEdit(); } private void tvIndex_AfterLabelEdit(object sender, NodeLabelEditEventArgs e) { this.tvIndex.SelectedNode.Name = e.Label; TreeNode node = this.tvIndex.SelectedNode; if (node.Tag is CHMDocument) { ((CHMDocument)node.Tag).Title = e.Label; } if (node.Tag is CHMNode) { ((CHMNode)node.Tag).Name = e.Label; } }
删除节点,即移除,同时还要删除文件
/// <summary> /// 删除节点 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void DeleteDToolStripMenuItem_Click(object sender, EventArgs e) { System.Windows.Forms.TreeNode node = this.tvIndex.SelectedNode;//获取要删除的节点 if (node == null) { MessageBox.Show("请选择一个节点"); return; } System.Windows.Forms.TreeNode parent = node.Parent;//获取该节点的父节点 if (parent == null) { MessageBox.Show("请选择目录或页面节点"); return; } CHMNodeList list = GetNodeList(parent); if (MessageBox.Show("是否删除文章(删除同时删除本地文件)?","确认", MessageBoxButtons.YesNo)== System.Windows.Forms.DialogResult.Yes) { list.Remove((CHMNode)node.Tag); //同时删除文件 if (System.IO.File.Exists(((CHMNode)node.Tag).Local)) { System.IO.File.Delete(((CHMNode)node.Tag).Local); } node.Remove();//移除该节点 } }
代码库搜索功能(Lucene.Net 2.0.04)
这个搜索只是简单的使用Lucene.Net实现的搜索。
我们在点击搜索按钮的时候,才开始做索引的操作。遍历chmDocument这个类,将节点信息存储为索引,然后查的时候就去查索引,好像有点多此一举。
其实不然,因为我们要全文模糊检索,我们不能看将每个文件打开,然后找找里面有没有这个搜索词。所以就用Lucene.Net。
具体实现代码如下:
/// <summary> /// 查询(修改为在点击查询的时候再去索引什么) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSearch_Click(object sender, EventArgs e) { //INDEX_STORE_PATH 为索引存储目录 string INDEX_STORE_PATH = Application.StartupPath+@"\index"; //先存储索引 IndexWriter writer = new IndexWriter(INDEX_STORE_PATH, new StandardAnalyzer(), true); SetIndex(writer,this.nodes); //在从索引中查询 string KEYWORD = this.txtKeyWords.Text.ToString();//关键字 IndexSearcher searcher; try { searcher = new IndexSearcher(INDEX_STORE_PATH); QueryParser q = null; if (rbByTitle.Checked) { q = new QueryParser("title", new StandardAnalyzer()); } else if (rbByKeywords.Checked) { q = new QueryParser("keywords", new StandardAnalyzer()); } else if (rbByAll.Checked) { q = new QueryParser("contents", new StandardAnalyzer()); } Query qquery = q.Parse(KEYWORD); Hits hits = searcher.Search(query); //创建DataTable用于绑定 DataTable dtResult = new DataTable(); DataColumn dc1 = new DataColumn("Title", Type.GetType("System.String")); DataColumn dc2= new DataColumn("KeyWords", Type.GetType("System.String")); DataColumn dc3 = new DataColumn("Content", Type.GetType("System.String")); DataColumn dc4 = new DataColumn("FilePath", Type.GetType("System.String")); dtResult.Columns.Add(dc1); dtResult.Columns.Add(dc2); dtResult.Columns.Add(dc3); dtResult.Columns.Add(dc4); if (hits != null && hits.Length()>0) { for (int i = 0; i < hits.Length(); i++) { Document doc = hits.Doc(i); DataRow dr=dtResult.NewRow(); dr["Title"] = doc.Get("title");//文章标题 dr["KeyWords"] = doc.Get("keywords");//文章关键字 dr["Content"] = doc.Get("contents");//内容 dr["FilePath"] = doc.Get("filename");//文件路径 dtResult.Rows.Add(dr); } this.tcList.SelectedIndex = 1; this.dgvResult.DataSource = dtResult; this.dgvResult.Columns["FilePath"].Visible = false; } else { MessageBox.Show("没有查到相关记录!"); } searcher.Close(); } catch (Exception ex) { LogHelper.WriteLog(ex.Message); } }
其中,写入索引的代码如下,也是使用遍历的(一开始想当然地做了,结果老是死循环,看来递归还是没有掌握好)
/// <summary> /// 遍历chmDocument,将节点存储为索引 /// </summary> private void SetIndex(IndexWriter writer, CHMNodeList nodes) { if (this.nodes == null || this.nodes.Count == 0) { return; } foreach (CHMNode n in nodes) { //if (node.Nodes==null) if (n.ImageNo == "1")//使用imageNo来判断 { IndexFile(n, writer); } else { SetIndex(writer,n.Nodes); } } writer.Close();// 关闭writer } private void IndexFile(CHMNode node, IndexWriter writer) { try { Document doc = new Document(); doc.Add(new Field("filename", node.Local, Field.Store.YES, Field.Index.TOKENIZED)); doc.Add(new Field("title", node.Name, Field.Store.YES, Field.Index.TOKENIZED)); doc.Add(new Field("keywords", node.KeyWords, Field.Store.YES, Field.Index.TOKENIZED)); doc.Add(new Field("contents", new StreamReader(node.Local, System.Text.Encoding.Default))); writer.AddDocument(doc); } catch (FileNotFoundException fnfe) { LogHelper.WriteLog(fnfe.Message); } }
在搜索界面中还是用了TabControl,以前用过DevExpress的TabControl,它隐藏 TabControl标签有现成的方法的,但是MS的TabControl貌似没有这个方法,于是就弄了讨巧的方法,将TabControl放在一个Panel中,头部稍微超出Panel的边界,然后在Form_Load方法中写如下代码:
//隐藏TabContol的标签栏 this.tcList.SizeMode = TabSizeMode.Fixed; this.tcList.ItemSize = new Size(0, 1);
附件下载 AlexisEditor RC版
说明:如果没有重大bug或者是反馈了,这个系列就到这边结束了,后面有篇文章专门总结这一系列的,里面的知识点还是比较多的,希望里面的知识能够帮到大家。
附件:http://down.51cto.com/data/2358207
相关文章推荐
- C#生成CHM文件(应用篇)之代码库编辑器(4)【附程序最终版下载】
- C#生成CHM文件(应用篇)之代码库编辑器(5)【总结、程序、源代码】
- C#生成CHM文件(应用篇)之代码库编辑器(5)【总结、程序、源代码】
- C#生成CHM文件(应用篇)之代码库编辑器(3)【附源代码下载】
- C#生成CHM文件(应用篇)之代码库编辑器(3)【附源代码下载】
- C#生成CHM文件(应用篇)之代码库编辑器(1)
- C#生成CHM文件(应用篇)之代码库编辑器(1)
- C#生成CHM文件(应用篇)之代码库编辑器(2)
- C#生成CHM文件(应用篇)之代码库编辑器(2)
- C#生成CHM文件(应用篇)
- C#生成CHM文件(应用篇)
- C#生成CHM文件(应用篇)
- 用C#代码生成一个简单的PDF文件(转)
- C# 简单的从服务器下载文件代码 2
- Asp.net 2.0 用C# 创建 PDF文件[引用] (示例代码下载)
- C#生成CHM文件(汇总篇)
- C#上传下载文件ftp操作类FTPClient代码
- Unity3d 通过json文件使用C#脚本代码生成多个相机
- Asp.net 2.0 用C# 创建 PDF文件[引用] (示例代码下载)
- C#生成CHM帮助文件—>续