前段日子,一同事发一条信息问WO关于监控软件的事。说一个网友需要这方面的资料,在这之前
曾经在网上查过相关的资料,并用VC(MFC)写了一个简单的监控程序,但因没有保存。重做系统后就没了
(因为当时只是实验,所以将MFC项目的Folder直接默认的建在了C盘).故当时就只是简单的回他
说使用 SHChangeNotifyRegister API就可以了。事后,突然觉得应该把这个写成组件
那么以后就不需要重复的去写这些东西了。本来准备用VC来写,因为需要大量API及其声明。
但却因为我不会用VC来写ACTIVEX.只好选用较熟悉的 V B
WINDOWS要实现监控文件夹的方法不止一种。
你可以使用FindFirstChangeNotification,再结合WaitForMultipleObjects,和FindNextChangeNotification
实现。
也可以使用本文介绍DE SHChangeNotifyRegister 来实现。当然我更喜欢用 SHChangeNotifyRegister
SHChangeNotifyRegister 是整个监控文件夹的核心之所在,所以在往HA介绍之前,得先搞明白其具体内容
SHChangeNotifyRegisterMSDN上是这样声明的。
ULONG SHChangeNotifyRegister(HWND hwnd,
int fSources,
LONG fEvents,
UINT wMsg,
int cEntries,
SHChangeNotifyEntry *pfsne
);
第一个参数就不用详细说明了,老鬼都知道这是一个窗口句柄,指明在捕获到改变的时候将消息发到的窗体
第二个参数MSDN上讲的好象有问题(当然也有可能我理解上有问题)。
而第三个参数MSDN上讲的就给放屁一样,所以排除MSDN上重新进行讲一HA。
其中第二个参数是指明返回到窗体处理函数中的WPARAM所指向的地址处所存的数据格式
可以是SHCNF_IDLIST(0x0000)// LPITEMIDLIST
也可以SHCNF_PATHA (0x0001)// path name
如果是SHCNF_IDLIST 则WPARAM所指向的地址处存的是LPITEMIDLIST(windows的名字空间ID)
如果是SHCNF_PATHA则WPARAM所指向的地址处存的是路径.
当然这里路径很好理解就是我们通常见到的形如"C:/abc"这样的字符串。但名字空间又是个什么东西呢。
名字空间是windows里引入的目录管理概念。和路径的作用是一样的。当然你会问,和路径的作用一样
那要它做什么。用路径不就行了。当然微软不是SB.搞一个这东西出来,自然有他的作用。虽然路径是
我们常见的,但事实上windows并不使用路径来管理树状目录。使用路径只是为了兼容DOS下的习惯,另外
看着也方便,理解也容易。真正用于管理windows树状目录的是名字空间。
用过电脑的都知道。想用路径来访问windows 里的所有目录那基本上肯定是不可能的。
至少你导死都访问不到控制面板或者网上领居或者回收站这样的目录。
但事实上你却能够访问到他们,那么用路径访问不到,那他是用什么访问的呢。
当然那就是名字空间。
讲了这么多,那名字空间究竟是什么呢。其实很简单。名字空间就是名字的空间,是一个windows下所有
目录及文件的名字及约束(规则)的集合。
windows里的每个目录和文件,都有一个唯一的名字。这个名字不象路径那样容易记忆和理解,这个名字是
一个32位的数。
当然为了讲解方便,我们还要使用路径这个概念.
例如c:/abc/text/test.txt这样一个路径。所表示的信息有。
"c:/abc/text/test.txt" 是 "test.txt" 这个文件的全路径。而test.txt 是这个文件的名字
其中"c:/abc" 是文件夹"abc"的全路径(注意这里讲的是文件夹而不是目录--文件夹是路径体系的概念,而目录
是名字空间里的概念,当然我们会经常混用,这无所谓,不防碍理解)
abc 是这个文件夹的名字 "c:/abc/text" 是文件夹"text"的全路径,而text是这个s文件夹的名字.
其中text又是abc的子文件夹。test.txt是放在text文件夹里的。
C:则是一个盘符名
以上的概念应该都能明白,如果不明白的话,建设你去撞墙。
ha面我们开始一一对应。
其中C:在名字空间里的表示为FEAB2346(当然这是一个假设,真实中可能是别的)
同理abc也可以在名字空间里有个表示EA123456.
继续对应text->AAAA3DAB
test.txt->12345678
那么为了方便看全写在ha面
c: -> FEAB2346
abc-> EA123456
text -> AAAA3DAB
test.txt -> 12345678
从这个对应上可以很明白的推出一点。在名字空间里,如果想访问C盘就得使用FEAB2346(这是不对的
但为了理解,这里估且这样认为,后面会有说明)
那么如果想访问c:/abc应该怎么办呢.其实是一样的,路径体系里可以使用一个/来分隔表示
树状结构。在名字空间就更加方便.
直接把abc的ID附在C:ID的后面就可以了。所以
c:/abc 在名字空间里的全地址是
FEAB2346
EA123456
同理c:/abc/text 就是
FEAB2346
EA123456
AAAA3DAB
其它一样,就不继续推了,当然要明白一点的是,也是刚才说过的。名字空间和路径不是一一对应的。
名字空间能够访问的范围更大,而且还有一点要明确。路径是以盘符为根的。而名字空间的根为桌面。
其结构如ha.
桌面
--回收站
--网上邻居
--控制面板
.........
--C:
----abc
------text
--------test.txt
.........
--n:
现在应该知道刚才为什么说访问C盘的全地址用FEAB2346是不以的了吧。真正的全地址hai
应该在其前面再加一个桌面。
当然看了上面的说明,你会有种想打人的冲动.没办法,WO的表达能力就这 水平。
不过想你继续往HA看会再回过头来看看,慢慢就会明白的。
第三个参数是指要捕获的事件类型,这里我们捕获SHCNE_ALLEVENTS(0x7FFFFFFF) Or SHCNE_INTERRUPT(0x7FFFFFFF) 所有的事件。
第四个消息是指明要发送给窗体的消息,当然这个消息要自定义
这里我们把它定义为WM_SHNOTIFY = &H401
虽然在这里我是这样写的,但推荐使用 WM_*** = WM_USER+n的方法.
第五个参数是个整型数,和第六个一起使用.
为了更好讲解,先介绍第六个参数。
第六个参数是一个结构体的指针,先看其定义
typedef struct {
LPCITEMIDLIST pidl;
BOOL fRecursive;
} SHChangeNotifyEntry
从名字上就可以看出来,这是一个入口结构。 是说明我们要监控那个目录用的。
他的第一个元素是LPCITEMIDLIST类型的pidl,不要被这么长的名字吓到了。其实
很简单,这就是一个指针,指向就是前面我们讲到的名字空间ID的指针。
第二个元素说明是否监控子目录,TRUE的时候监控。否则不监控.
ha面讲第五个参数,因为说明了第六个,第五个就很好说明了。其实第五个参数就是说明。
第六个参数的数组个数的,看到这里可能你们有点糊涂。第六个参数不是一个结构体吗,
怎么成了数组了。在此声明一ha。从来没讲过第六个参数是一个结构体。因为一开始就讲
第六个参数是一个结构体的指针。当然这个描述不太准确的,在这里准确的说应该是一个
结构体数组的指针。
好了。几个参数已经讲完了,当然以我的表达能力能看懂的应该不是很多。所以现在再通盘的
描述一ha。
ULONG SHChangeNotifyRegister(HWND hwnd,
SHChangeNotifyEntry *pfsne
);
其实这个函数的作用,就是监控 由cEntries和pfsne所表明的一个目录(文件)或者一组目录(文件) 的变更。
当这些目录发生了fEvents所描述的事件范围内的事件的话,就将一个wMsg消息放到 窗体 hwnd
的消息队队列里。
好了核心函数到此已经介绍完了,继续开始往ha走。
------------------------------------------------------