桌面搜索项目【http://blog.youkuaiyun.com/fire_woods】

发起一个桌面搜索项目<script language="javascript" type="text/javascript"> document.title="发起一个桌面搜索项目 - "+document.title </script>

    桌面搜索现在做的比较热,主要有google,百度,雅虎,微软等,中国的有网络猪和88data。用下来感觉还是google的比较不错。

    由于手头也有一些这方面的技术,所以想发起一个桌面搜索的项目。

    桌面搜索主要的两个问题是搜索引擎和多种文件格式的支持,对于搜索引擎方面,我这里已经有现成的模块。文件格式支持就不是我一个人能做的了的了。现在手头有的技术有office系列,outlook,文本,pdf这些格式。对于其他的格式,想通过一种插件的方式实现,即给一个统一的接口模板,大家都用这个模板开发dll,主程序会自动将这些dll集成进来,遇到特定的格式,调用特定的dll去读取里面的文字内容。

    由于现在我这里blog刚开起来,没有多少人关注,所以我先自己把目录监控,主框架搭建,接后方式这些工作完成。格式解析先把我能解决的完成,其他的慢慢来,希望能有越来越多的人参与这个项目,制作出一套完美的桌面引擎出来。

桌面搜索项目正式启动<script language="javascript" type="text/javascript"> document.title="桌面搜索项目正式启动 - "+document.title </script>

经过一段时间的酝酿,桌面搜索项目正式启动了。

在vchelp中申请了一个项目空间

http://www.vchelp.net/copathway/project_view.asp?prj_id=1345

现在完成了框架搭建中的系统托盘部分的工作。

希望大家捧场:)

桌面搜索-系统托盘<script language="javascript" type="text/javascript"> document.title="桌面搜索-系统托盘 - "+document.title </script>

在程序最小化时,不在windows的任务栏中出现,而是在右下角的系统托盘中显示一个小图标,当鼠标单击时显示功能菜单,双击时打开主界面。这就是系统托盘程序的一般功能,想qq和很多桌面搜索程序都是这么做了,给人的感觉比较清爽,不用的时候就缩在一个小角落里,用的时候也能很快的找到。

在技术实现上

首先是创建托盘:

void CDiskSearchDlg::InitTray()
{
 m_NotifyID.cbSize=(DWORD)sizeof(NOTIFYICONDATA);
 m_NotifyID.hWnd=this->m_hWnd;
 m_NotifyID.uID=IDR_MAINFRAME;
 m_NotifyID.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP ;
 m_NotifyID.uCallbackMessage=WM_NOTIFYICON;//自定义的消息名称
 m_NotifyID.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
 strcpy(m_NotifyID.szTip,"桌面搜索");//信息提示
 Shell_NotifyIcon(NIM_ADD,&m_NotifyID);//在托盘区添加图标
}

上面的代码就是一个一般创建的方法,其中定义NOTIFYICONDATA m_NotifyID;

WM_NOTIFYICON是自定义的消息,我们可以用

#define WM_NOTIFYICON WM_USE+5

来定义

调用InitTray()后会在托盘上出现一个小图标,当然我们也同时要把任务栏中的程序任务去掉,只要调用ShowWindow(SW_HIDE)就可以了

接下来是创建一个菜单资源,假设为IDR_MENU_TP

然后要做的是添加WM_NOTIFYICON消息:

在BEGIN_MESSAGE_MAP(CDiskSearchDlg, CDialog)内要添加

ON_MESSAGE(WM_NOTIFYICON, OnNotifyIcon)//手工添加托盘消息映射

并定义函数

LONG CDiskSearchDlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
{
 //wParam中是响应消息的图标ID,lParam中则是Windows的消息
    switch ( lParam )
 {
 case WM_RBUTTONDOWN:
  {// 用户在托盘图标上单击鼠标右键,弹出菜单
   CMenu pMenu;
   if (pMenu.LoadMenu(IDR_MENU_TP))
   {
    CMenu* pPopup = pMenu.GetSubMenu(0);
    ASSERT(pPopup != NULL);
    CPoint Point;
    GetCursorPos( &Point );
    SetForegroundWindow();
    pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, Point.x, Point.y, this);
   }          
  }
  break;
 case WM_LBUTTONDBLCLK:
//  OnMenuitemShow();
  break;
 case WM_LBUTTONDOWN:
  {// 用户在托盘图标上单击鼠标右键,弹出菜单
   CMenu pMenu;
   if (pMenu.LoadMenu(IDR_MENU_TP))
   {
    CMenu* pPopup = pMenu.GetSubMenu(0);
    ASSERT(pPopup != NULL);
    CPoint Point;
    GetCursorPos( &Point );
    SetForegroundWindow();
    pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, Point.x, Point.y, this);
   }          
  }
  break;
 default:break;
 }
    return 0;
}

上面这段代码中,添加了鼠标单击的消息,双击和其他消息其实是一样的。

最后,在退出的时候记得要调用

Shell_NotifyIcon(NIM_DELETE, &m_NotifyID);

来把托盘图标删除。

当然还有做动画托盘,就是托盘上的图标是变化的,这个可以在上面的dlg类中添加Timer函数,定时更换图标就可以了。

桌面搜索项目人员到位<script language="javascript" type="text/javascript"> document.title="桌面搜索项目人员到位 - "+document.title </script>

经过3天的筹划,桌面搜索项目的10名人员均已经到位,项目正式启动。

这星期的工作主要是项目组成员互相熟悉,项目工作安排等。

下周开始进行技术研发和编码阶段。

桌面搜索-开发计划完成<script language="javascript" type="text/javascript"> document.title="桌面搜索-开发计划完成 - "+document.title </script>

今天把开发计划完成了,在这里贴个目录吧,想知道详细内容的可以到项目的开发网站上下载文档查看,多提宝贵意见,好的开始是成功的一半。

http://www.vchelp.net/copathway/project_view.asp?prj_id=1345

 

桌面搜索-开发计划完成<script language="javascript" type="text/javascript"> document.title="桌面搜索-开发计划完成 - "+document.title </script>

今天把开发计划完成了,在这里贴个目录吧,想知道详细内容的可以到项目的开发网站上下载文档查看,多提宝贵意见,好的开始是成功的一半。

http://www.vchelp.net/copathway/project_view.asp?prj_id=1345

 

1.    技术架构... 2

1.1.     主线程... 3

1.2.     文件索引线程... 3

1.3.     目录监控线程... 3

2.    功能模块划分... 3

2.1.     全文检索模块... 3

2.2.     目录监控模块... 3

2.3.     插件模块... 4

2.3.1.      插件格式... 4

2.3.2.      插件注册... 4

2.3.3.      分析文件... 5

2.3.4.      判断支持... 5

2.3.5.      插件测试程序... 5

2.3.6.      插件类型... 5

2.4.     索引模块... 5

2.5.     搜索界面... 5

2.6.     功能表... 6

3.    数据结构... 6

4.    约束... 6

1.    技术架构... 2

1.1.     主线程... 3

1.2.     文件索引线程... 3

1.3.     目录监控线程... 3

2.    功能模块划分... 3

2.1.     全文检索模块... 3

2.2.     目录监控模块... 3

2.3.     插件模块... 4

2.3.1.      插件格式... 4

2.3.2.      插件注册... 4

2.3.3.      分析文件... 5

2.3.4.      判断支持... 5

2.3.5.      插件测试程序... 5

2.3.6.      插件类型... 5

2.4.     索引模块... 5

2.5.     搜索界面... 5

2.6.     功能表... 6

3.    数据结构... 6

4.    约束... 6

1.    技术架构... 2

1.1.     主线程... 3

1.2.     文件索引线程... 3

1.3.     目录监控线程... 3

2.    功能模块划分... 3

2.1.     全文检索模块... 3

2.2.     目录监控模块... 3

2.3.     插件模块... 4

2.3.1.      插件格式... 4

2.3.2.      插件注册... 4

2.3.3.      分析文件... 5

2.3.4.      判断支持... 5

2.3.5.      插件测试程序... 5

2.3.6.      插件类型... 5

2.4.     索引模块... 5

2.5.     搜索界面... 5

2.6.     功能表... 6

3.    数据结构... 6

4.    约束... 6

桌面搜索-开发计划完成<script language="javascript" type="text/javascript"> document.title="桌面搜索-开发计划完成 - "+document.title </script>

今天把开发计划完成了,在这里贴个目录吧,想知道详细内容的可以到项目的开发网站上下载文档查看,多提宝贵意见,好的开始是成功的一半。

http://www.vchelp.net/copathway/project_view.asp?prj_id=1345

 

1.    技术架构... 2

1.1.     主线程... 3

1.2.     文件索引线程... 3

1.3.     目录监控线程... 3

2.    功能模块划分... 3

2.1.     全文检索模块... 3

2.2.     目录监控模块... 3

2.3.     插件模块... 4

2.3.1.      插件格式... 4

2.3.2.      插件注册... 4

2.3.3.      分析文件... 5

2.3.4.      判断支持... 5

2.3.5.      插件测试程序... 5

2.3.6.      插件类型... 5

2.4.     索引模块... 5

2.5.     搜索界面... 5

2.6.     功能表... 6

3.    数据结构... 6

4.    约束... 6

1.    技术架构... 2

1.1.     主线程... 3

1.2.     文件索引线程... 3

1.3.     目录监控线程... 3

2.    功能模块划分... 3

2.1.     全文检索模块... 3

2.2.     目录监控模块... 3

2.3.     插件模块... 4

2.3.1.      插件格式... 4

2.3.2.      插件注册... 4

2.3.3.      分析文件... 5

2.3.4.      判断支持... 5

2.3.5.      插件测试程序... 5

2.3.6.      插件类型... 5

2.4.     索引模块... 5

2.5.     搜索界面... 5

2.6.     功能表... 6

3.    数据结构... 6

4.    约束... 6

1.    技术架构... 2

1.1.     主线程... 3

1.2.     文件索引线程... 3

1.3.     目录监控线程... 3

2.    功能模块划分... 3

2.1.     全文检索模块... 3

2.2.     目录监控模块... 3

2.3.     插件模块... 4

2.3.1.      插件格式... 4

2.3.2.      插件注册... 4

2.3.3.      分析文件... 5

2.3.4.      判断支持... 5

2.3.5.      插件测试程序... 5

2.3.6.      插件类型... 5

2.4.     索引模块... 5

2.5.     搜索界面... 5

2.6.     功能表... 6

3.    数据结构... 6

4.    约束... 6

桌面搜索-UNICODE支持<script language="javascript" type="text/javascript"> document.title="桌面搜索-UNICODE支持 - "+document.title </script>

现在很多软件都向国际化版本靠拢,对UNICODE方式的支持也似乎逐渐成为众多软件开发者的追求。

对于桌面搜索,对UNICODE的支持非常重要。搜索引擎本身支持非UNICODE和UNICODE两中模式的,但是在实际的应用中,采用UNICODE方式会带来更多的便利,主要体现是在分词上,由于非UNICODE方式,英文字母是一个直接而汉字是两个直接,导致分词相对来说比UNICODE方式要复杂,我们不得不对每个字节去判断是汉字的半个字还是一个ASC码。

当然为了那些不支持UNICODE的windows操作系统(如95),程序也需要在非UNICODE模式下运行。所以,最终的方案是支持多种编译模式,根据需要编译出不同的版本。

为了支持不同的编译模式,我们需要改写我们习惯上的大部分字符串和内存相关的变量和函数。在TCHAR.h中对这些函数进行了映射。打个简单的比方,对于字符的定义如下:

#ifdef _UNICODE

typedef short       TCHAR;

#else

typedef char            TCHAR;

#endif

也就是说在我们什么的_UNICODE编译模式下,会采用双字节来存储一个字符,而非UNICODE模式下就是单字节。我们在写代码声明字符时,就需要用

TCHAR cTemp;

的方式,这样无论那种模式都可以支持。

同样的,对于字符串操作和内存操作函数也需要相应的改变,如strcpy要改成_tcspy。

在实际应用中,我们需要关心的有下面这些:

TCHAR,LPTSTR,LPCTSTR,str开头的函数都编程_tcs开头,_T

特别要说一下的是_T,一般我们给字符串赋常量时是用"aaa"方式,但是在这里我们就需要用_T("aaa")。

说完编码时候需哟注意的问题,下面要说的是怎么设置编译模式,一般创建工程后有2种编译模式,debug和release。首先我们要添加新的编译模式。

在build->configuations里面添加Debug_Unicode和Release_Unicode

然后在Project->settings中设置这两个编译模式:

1.在c/c++页中Preprocessor definitions的最后添加,_UNICODE  表示UNICODE编译模式

2.在link->Project options中添加/entry:"wWinMainCRTStartup" 表示采用wWinMainCRTStartup 入口,这是因为unicode版本程序入口为wWinMainCRTStartup 。如果不加的话会出现error LNK2001: unresolved external symbol _WinMain@16的链接错误。

最后需要说明的一点是,关于国际化版本。一个理想的过程是在国际化时(如中文版变成英文版),做国际化的人不需要拿到源代码也能翻译。这个就需要我们把所有的字符串都放在固定的文本文件或者是资源文件中,国际化时只需要修改这两个文件就可以了。

桌面搜索-目录监控<script language="javascript" type="text/javascript"> document.title="桌面搜索-目录监控 - "+document.title </script>

对于桌面搜索来说,需要随时观察硬盘的中文件是否有变化,对于新增的文件要添加索引,对于删除的文件要删除相应的索引,对于修改,重命名等也需要做相应的处理,这样才能保证我们的桌面搜索引擎总是能够搜索到最新最全的硬盘中的信息。

对于windows操作系统,监控目录的方法一般有下面这些:

1.文件同步

文件同步方法的大致思想是在程序启动时,在内存中建立一棵与硬盘中文件和目录结构一一对于的文件树。并每隔几分钟扫描一次硬盘,对于硬盘中文件或者目录与内存中不符的部分做相应的处理,并更新文件树。对于象桌面搜索这里的应用来说,并不需要时时,所以几分钟同步一次问题不是很大。然而在同步效率方面,由于要遍历硬盘上的所有文件,消耗的时间还是很大的。我做测试的硬盘有80G,一共有60000多个目录和4000多个目录,遍历一次硬盘的时间大概需要1秒多的时间,如果文件更多的话,就很难接受了。

至于改进的办法,我想可以从2方面来进行。

一个是降低遍历线程的优先级,就是花更多的时间遍历,但是不影响系统别的进行的运行,现在我一遍历,硬盘就嗞嗞做响。

另外一个方法是只遍历关心的文件,由于桌面搜索只是对部分格式的文件做全文检索,其他只要检索文件名就可以了。所以我们在遍历是只搜索特殊后缀的文件,不过这个可能对性能的提高不会有太多的影响。

2.虚拟设备驱动(VXD)编程

设备驱动编程是指让工作于系统核心态的驱动程序去拦截所有的文件访问。这种方法时时性高,但是风险很大,由于设备驱动编程需要进入ring0权限,所以将很容易导致蓝屏死机(BSOD),Ring0下的异常将往往导致系统崩溃,因为它对于系统总是被信任的,所以没有相应处理代码去捕获这个异常。另外实现相对复杂很多,所以除了杀毒软件采用这种方式以外,其他很少有用到这种方式监控目录的。

3.Windows API

windows API方式主要采用windows提供的api接口来完成对目录的监控,实现相对简单。我们的桌面搜索引擎也准备采用这种模式来实现。

Windows里面对目录、文件监控提供了两个API,它们分别是:FindFirstChangeNotificationReadDirectoryChangesW。这两个API都可以对目录进行时时监控。

但是非常不幸的,他们都有自己的缺点(要是没有缺点的话杀毒软件也不会费那么大力,冒那么大风险用设备驱动编程方式了)。首先说FindFirstChangeNotification,这个API最大的问题是告诉你了某个目录有变化,但是却不告诉你变化在哪里,简直是让人吐血。在桌面搜索中,一般是对系统的分区进行监控的,你告诉我C:发生了变化,其实一点用都没有,我还是要把C:全部搜索一遍。当然FindFirstChangeNotification也可以不对子目录进行监控,我测试了一下,对6000多个目录全部建立的监控(当然是一个线程),结果发现监控失败,最终测试结果是FindFirstChangeNotification最多只支持监控64个目录。所以只好放弃了。

ReadDirectoryChangesW到是对上面的这些非常支持,简直说是完美无缺,不仅告诉你哪个文件改变了,是大小改变还是被修改或者创建删除重命名都给你分的轻轻楚楚,但是只支持2000及以上的windows版本。真是无奈啊,所以我们的桌面搜索引擎只好只支持2000及以上版本了。

最后,我觉得第一种方法虽然速度慢,但是还有改进的余地,如果有时间的话我会再尝试的。如果大家有什么好的方法,也希望多多指教。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值