一个关于 Windows Message 的问题 from 3h(300分)

  • 主题发起人 主题发起人 3h
  • 开始时间 开始时间
试了一下,基本能用,它能够捕获文件系统的变化,不过结果很简单,就只一个事件,<br>ONCHANGE。<br>它也只有两个参数:sender和所在目录。<br>如果象资源管理器一样能够知道是那一个文件就好了。
 
用COM对象, 实现诸如 ICopyHook之类的接口可以截获很多功能, Delphi有一个<br>Demo, 就是CopyHook的.<br>
 
cmxu说的对,这属于shell扩展,Delphi的/demo/Activex/shellext/下
 
最好有例程。
 
//faint.<br>Delphi的方法与这个SysMonitor的方法是不一样的.<br>在Windows下面要监控一个目录只能用Another_eYes的方法,即是<br>调用CreateFile与CreateCompletionPort的方法来做,然后用<br>FindFirstChangeNotification<br>FindNextChangeNotification<br>来得知目录的变化.<br>在WinNT下面有一个很好的函数叫ReadDirectoryChangesW<br>函数,调用以下函数:<br>CreateFile<br>CreateCompletionPort<br>ReadDirectoryChangesW<br>GetOverLappedResult<br>这几个函数就可以创建一个线程来监控一个目录了,<br>而且可以得到很详细的信息.<br>SysMonitor用的是Another_eYes的方法,但是如果你在NT下面,<br>则可以自己写一个监控线程,很容易的.<br>:)
 
现在我吧代码贴上来吧: DiscMonitor:<br>// ==================== DISC DRIVE MONITOR =====================================<br>//<br>// Class and Component to encapsulate the FindXXXXChangeNotification API calls<br>//<br>// The FindXXXXChangeNotification API calls set up a disc contents change<br>// notification handle. &nbsp;You can set a filter to control which change types<br>// are notified, the directory which is monitored and set whether subdirectories<br>// from the monitored directory are monitored as well.<br>//<br>//------------------------------------------------------------------------------<br>// This file contains a class derived from TThread which undertakes the disc<br>// monitoring and a simple component which encapsulates the thread to make<br>// a non-visual VCL component. &nbsp;This component works at design time, monitoring<br>// and notifying changes live if required.<br>//<br>// Version 1.00 - Grahame Marsh 14 January 1997<br>// Version 1.01 - Grahame Marsh 30 December 1997<br>// &nbsp; &nbsp; &nbsp;Bug fix - really a Win 95 bug but only surfaces in D3, not D2<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- see notes in execute method<br>// Version 1.02 - Grahame Marsh 30 January 1998<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- adapted to work with version 2.30 TBrowseDirectoryDlg<br>//<br>// Freeware - you get it for free, I take nothing, I make no promises!<br>//<br>// Please feel free to contact me: grahame.s.marsh@courtaulds.com<br><br>unit DiscMon;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Classes, Graphics, Controls,<br>&nbsp; Forms, Dialogs, ShlObj{, BrowseDr, DsgnIntf ie02};<br><br>//=== DISC MONITORING THREAD ===================================================<br>// This thread will monitor a given directory and subdirectories (if required)<br>// for defined filtered changes. &nbsp;When a change occurs the OnChange event will<br>// be fired, if an invalid condition is found (eg non-existent path) then<br>// the OnInvalid event is fired. Each event is called via the Sychronize method<br>// and so are VCL thread safe.<br>//<br>// The thread is created suspended, so after setting the required properties<br>// you must call the Resume method.<br><br><br>type<br>&nbsp; TDiscMonitorThread = class(TThread)<br>&nbsp; private<br>&nbsp; &nbsp; FOnChange : TNotifyEvent;<br>&nbsp; &nbsp; FOnInvalid : TNotifyEvent;<br>&nbsp; &nbsp; FDirectory : string;<br>&nbsp; &nbsp; FFilters : integer;<br>&nbsp; &nbsp; FDestroyEvent,<br>&nbsp; &nbsp; FChangeEvent : THandle;<br>&nbsp; &nbsp; FSubTree : boolean;<br>&nbsp; &nbsp; fChangeDelay : Integer; &nbsp;{ie01}<br>&nbsp; &nbsp; procedure InformChange;<br>&nbsp; &nbsp; procedure InformInvalid;<br>&nbsp; &nbsp; procedure SetDirectory (const Value : string);<br>&nbsp; &nbsp; procedure SetFilters (Value : integer);<br>&nbsp; &nbsp; procedure SetSubTree (Value : boolean);<br>&nbsp; protected<br>&nbsp; &nbsp; procedure Execute; override;<br>&nbsp; &nbsp; procedure Update;<br>&nbsp; public<br>&nbsp; &nbsp; constructor Create;<br>&nbsp; &nbsp; destructor Destroy; override;<br>// The directory to monitor<br>&nbsp; &nbsp; property Directory : string read FDirectory write SetDirectory;<br>// Filter condition, may be any of the FILE_NOTIFY_CHANGE_XXXXXXX constants<br>// ORed together. &nbsp;Zero is invalid.<br>&nbsp; &nbsp; property Filters : integer read FFilters write SetFilters;<br>// Event called when change noted in directory<br>&nbsp; &nbsp; property OnChange : TNotifyEvent read FOnChange write FOnChange;<br>// Event called for invalid parameters<br>&nbsp; &nbsp; property OnInvalid : TNotifyEvent read FOnInvalid write FOnInvalid;<br>// Include subdirectories below specified directory.<br>&nbsp; &nbsp; property SubTree : boolean read FSubTree write SetSubTree;<br>// specify, how long the thread should wait, before the event OnChange is fired:<br>&nbsp; &nbsp; Property ChangeDelay : Integer Read fChangeDelay Write fChangeDelay &nbsp;{ie01}<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Default 500; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ie01}<br>&nbsp; end;<br><br>//===================== DISC MONITORING COMPONENT ==============================<br><br>// specify directory string as type string so we can have our own property editor<br>&nbsp; TDiscMonitorDirStr = type string;<br><br>// enumerated type for filter conditions (not directly usable in thread class)<br>// see the SetFilters procedure for the translation of these filter conditions<br>// into FILE_NOTIFY_CHANGE_XXXXXX constants.<br>&nbsp; TMonitorFilter = (moFilename, moDirName, moAttributes, moSize,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; moLastWrite, moSecurity);<br>// set of filter conditions<br>&nbsp; TMonitorFilters = set of TMonitorFilter;<br><br>&nbsp; TDiscMonitor = class(TComponent)<br>&nbsp; private<br>&nbsp; &nbsp; FActive : boolean;<br>&nbsp; &nbsp; FMonitor : TDiscMonitorThread;<br>&nbsp; &nbsp; FFilters : TMonitorFilters;<br>&nbsp; &nbsp; FOnChange : TNotifyEvent;<br>&nbsp; &nbsp; FOnInvalid : TNotifyEvent;<br>&nbsp; &nbsp; FShowMsg : boolean;<br>&nbsp; &nbsp; function GetDirectory : TDiscMonitorDirStr;<br>&nbsp; &nbsp; function GetSubTree : boolean;<br>&nbsp; &nbsp; procedure SetActive (Value : boolean);<br>&nbsp; &nbsp; procedure SetDirectory (Value : TDiscMonitorDirStr);<br>&nbsp; &nbsp; procedure SetFilters (Value : TMonitorFilters);<br>&nbsp; &nbsp; procedure SetSubTree (Value : boolean);<br>&nbsp; &nbsp; Function &nbsp;GetChangeDelay : Integer; &nbsp; &nbsp; &nbsp; &nbsp; {ie01}<br>&nbsp; &nbsp; Procedure SetChangeDelay(Value : Integer); &nbsp;{ie01}<br>&nbsp; protected<br>&nbsp; &nbsp; procedure Change (Sender : TObject);<br>&nbsp; &nbsp; procedure Invalid (Sender : TObject);<br>&nbsp; public<br>&nbsp; &nbsp; constructor Create (AOwner : TComponent); &nbsp;Override;<br>&nbsp; &nbsp; destructor Destroy; override;<br>// stop the monitoring thread running<br>&nbsp; &nbsp; procedure Close;<br>// start the monitoring thread running<br>&nbsp; &nbsp; procedure Open;<br>// read-only property to access the thread directly<br>&nbsp; &nbsp; property Thread : TDiscMonitorThread read FMonitor;<br>&nbsp; published<br>// the directory to monitor<br>&nbsp; &nbsp; property Directory : TDiscMonitorDirStr read GetDirectory write SetDirectory;<br>// control the appearance of information messages at design time (only)<br>&nbsp; &nbsp; property ShowDesignMsg : boolean read FShowMsg write FShowMsg default false;<br>// event called when a change is notified<br>&nbsp; &nbsp; property OnChange : TNotifyEvent read FOnChange write FOnChange;<br>// event called if an invalid condition is found<br>&nbsp; &nbsp; property OnInvalid : TNotifyEvent read FOnInvalid write FOnInvalid;<br>// notification filter conditions<br>&nbsp; &nbsp; property Filters : TMonitorFilters read FFilters write SetFilters default [moFilename];<br>// include subdirectories below the specified directory<br>&nbsp; &nbsp; property SubTree : boolean read GetSubTree write SetSubTree default true;<br>// specify if the monitoring thread is active<br>&nbsp; &nbsp; property Active : boolean read FActive write SetActive default false;<br>// specify, how long the thread should wait, before the event OnChange is fired:<br>&nbsp; &nbsp; Property ChangeDelay : Integer Read GetChangeDelay Write SetChangeDelay &nbsp;{ie01}<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Default 500; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ie01}<br>&nbsp; end;<br><br>procedure Register;<br><br>implementation<br><br>//=== MONITOR THREAD ===========================================================<br><br>// Create the thread suspended. &nbsp;Create two events, each are created using<br>// standard security, in the non-signalled state, with auto-reset and without<br>// names. &nbsp;The FDestroyEvent will be used to signal the thread that it is to close<br>// down. &nbsp;The FChangeEvent will be used to signal the thread when the monitoring<br>// conditions (directory, filters or sub-directory search) have changed.<br>// OnTerminate is left as false, so the user must Free the thread.<br><br>constructor TDiscMonitorThread.Create;<br>begin<br>&nbsp; inherited Create (true);<br>&nbsp; FDestroyEvent := CreateEvent (nil, true, &nbsp;false, NIL);<br>&nbsp; FChangeEvent &nbsp;:= CreateEvent (nil, false, false, NIL);<br>end;<br><br>// close OnXXXXX links, signal the thread that it is to close down<br>destructor TDiscMonitorThread.Destroy;<br>begin<br>&nbsp; FOnChange := nil;<br>&nbsp; FOnInvalid := nil;<br>&nbsp; SetEvent (FDestroyEvent);<br>&nbsp; FDirectory := '';<br>&nbsp; inherited Destroy<br>end;<br><br>// called by the Execute procedure via Synchronize. &nbsp;So this is VCL thread safe<br>procedure TDiscMonitorThread.InformChange;<br>begin<br>&nbsp; if Assigned (FOnChange) then<br>&nbsp; &nbsp; FOnChange (Self)<br>end;<br><br>// called by the Execute procedure via Synchronize. &nbsp;So this is VCL thread safe<br>procedure TDiscMonitorThread.InformInvalid;<br>begin<br>&nbsp; if Assigned (FOnInvalid) then<br>&nbsp; &nbsp; FOnInvalid (Self)<br>end;<br><br>// Change the current directory<br>procedure TDiscMonitorThread.SetDirectory (const Value : string);<br>begin<br>&nbsp; if Value &lt;&gt; FDirectory then<br>&nbsp; begin<br>&nbsp; &nbsp; FDirectory := Value;<br>&nbsp; &nbsp; Update<br>&nbsp; end<br>end;<br><br>// Change the current filters<br>procedure TDiscMonitorThread.SetFilters (Value : integer);<br>begin<br>&nbsp; if Value &lt;&gt; FFilters then<br>&nbsp; begin<br>&nbsp; &nbsp; FFilters := Value;<br>&nbsp; &nbsp; Update<br>&nbsp; end<br>end;<br><br>// Change the current sub-tree condition<br>procedure TDiscMonitorThread.SetSubTree (Value : boolean);<br>begin<br>&nbsp; if Value &lt;&gt; FSubTree then<br>&nbsp; begin<br>&nbsp; &nbsp; FSubtree := Value;<br>&nbsp; &nbsp; Update<br>&nbsp; end<br>end;<br><br><br>Function TDiscMonitor.GetChangeDelay : Integer; &nbsp;{ie01}<br>begin<br>&nbsp; Result := FMonitor.ChangeDelay;<br>end;<br><br><br>Procedure TDiscMonitor.SetChangeDelay(Value : Integer); &nbsp;{ie01}<br>begin<br>&nbsp; FMonitor.ChangeDelay := Value;<br>end;<br><br><br>// On any of the above three changes, if the thread is running then<br>// signal it that a change has occurred.<br>procedure TDiscMonitorThread.Update;<br>begin<br>&nbsp; if not Suspended then<br>&nbsp; &nbsp; SetEvent (FChangeEvent)<br>end;<br><br>// The EXECUTE procedure<br>// &nbsp; &nbsp; -------<br>// Execute needs to:<br>// 1. Call FindFirstChangeNotification and use the Handle in a WaitFor...<br>// &nbsp; &nbsp;to wait until the thread become signalled that a notification has occurred.<br>// &nbsp; &nbsp;The OnChange event is called and then the FindNextChangeNotification is<br>// &nbsp; &nbsp;the called and Execute loops back to the WaitFor<br>// 2. If an invalid handle is obtained from the above call, the the OnInvalid<br>// &nbsp; &nbsp;event is called and then Execute waits until valid conditions are set.<br>// 3. If a ChangeEvent is signalled then FindCloseChangeNotification is called,<br>// &nbsp; &nbsp;followed by a new FindFirstChangeNotification to use the altered<br>// &nbsp; &nbsp;conditions.<br>// 4. If a DestroyEvent is signalled then FindCloseChangeNotification is<br>// &nbsp; &nbsp;called and the two events are closed and the thread terminates.<br>//<br>// In practice WaitForMultipleObjects is used to wait for any of the conditions<br>// to be signalled, and the returned value used to determine which event occurred.<br><br>procedure TDiscMonitorThread.Execute;<br>// There appears to be a bug in win 95 where the bWatchSubTree parameter<br>// of FindFirstChangeNotification which is a BOOL only accepts values of<br>// 0 and 1 as valid, rather than 0 and any non-0 value as it should. &nbsp;In D2<br>// BOOL was defined as 0..1 so the code worked, in D3 it is 0..-1 so<br>// fails. The result is FindF... produces and error message. &nbsp;This fix (bodge) is<br>// needed to produce a 0,1 bool pair, rather that 0,-1 as declared in D3<br>const<br>&nbsp; R : array [false..true] of BOOL = (BOOL (0), BOOL (1));<br>var<br>&nbsp; A : array [0..2] of THandle; // used to give the handles to WaitFor...<br>&nbsp; B : boolean; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // set to true when the thread is to terminate<br>begin<br>&nbsp; B := false;<br>&nbsp; A [0] := FDestroyEvent; &nbsp; &nbsp; &nbsp;// put DestroyEvent handle in slot 0<br>&nbsp; A [1] := FChangeEvent; &nbsp; &nbsp; &nbsp; // put ChangeEvent handle in slot 1<br>// make the first call to the change notification system and put the returned<br>// handle in slot 2.<br>&nbsp; A [2] := FindFirstChangeNotification (PChar(FDirectory), R[fSubTree], FFilters);<br>&nbsp; repeat<br><br>// if the change notification handle is invalid then:<br>&nbsp; &nbsp; if A [2] = INVALID_HANDLE_VALUE then<br>&nbsp; &nbsp; begin<br>&nbsp; // call the OnInvalid event<br>&nbsp; &nbsp; &nbsp; Synchronize (InformInvalid);<br>&nbsp; // wait until either DestroyEvent or the ChangeEvents are signalled<br>&nbsp; &nbsp; &nbsp; case WaitForMultipleObjects (2, PWOHandleArray (@A), false, INFINITE) - WAIT_OBJECT_0 of<br>&nbsp; // DestroyEvent - close down by setting B to true<br>&nbsp; &nbsp; &nbsp; &nbsp; 0 : B := true;<br>&nbsp; // try new conditions and loop back to the invalid handle test<br>&nbsp; &nbsp; &nbsp; &nbsp; 1 : A [2] := FindFirstChangeNotification (PChar(FDirectory), R[fSubTree], FFilters)<br>&nbsp; &nbsp; &nbsp; end<br>&nbsp; &nbsp; end else<br>// handle is valid so wait for any of the change notification, destroy or<br>// change events to be signalled<br>&nbsp; &nbsp; &nbsp; case WaitForMultipleObjects (3, PWOHandleArray (@A), false, INFINITE) - WAIT_OBJECT_0 of<br>&nbsp; &nbsp; &nbsp; &nbsp; 0 : begin<br>&nbsp; // DestroyEvent signalled so use FindClose... and close down by setting B to true<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FindCloseChangeNotification (A [2]);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; B := true<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; 1 : begin<br>&nbsp; // ChangeEvent signalled so close old conditions by FindClose... and start<br>&nbsp; // off new conditions. &nbsp;Loop back to invalid test in case new conditions are<br>&nbsp; // invalid<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FindCloseChangeNotification (A [2]);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; A [2] := FindFirstChangeNotification (PChar(FDirectory), R[fSubTree], FFilters)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; 2 : begin<br>&nbsp; // Notification signalled, so fire the OnChange event and then FindNext..<br>&nbsp; // loop back to re-WaitFor... the thread<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Sleep(fChangeDelay); &nbsp;{ie01 ins}<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Synchronize (InformChange);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FindNextChangeNotification (A [2])<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; end<br>&nbsp; until B Or Self.Terminated;<br><br>// closing down so chuck the two events<br>&nbsp; CloseHandle (FChangeEvent);<br>&nbsp; CloseHandle (FDestroyEvent)<br>end;<br><br>//=== MONITOR COMPONENT ========================================================<br><br>// This component encapsulates the above thread. &nbsp;It has properties for<br>// directory, sub-directory conditions, filters, whether information messages<br>// should be given at design time and if the thread is active.<br>constructor TDiscMonitor.Create (AOwner : TComponent);<br>begin<br>&nbsp; inherited Create (AOwner);<br>&nbsp; FMonitor := TDiscMonitorThread.Create; &nbsp;// create a monitor thread<br>&nbsp; FMonitor.ChangeDelay := 500; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ie01}<br>&nbsp; FMonitor.OnChange := Change; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// hook into its event handlers<br>&nbsp; FMonitor.OnInvalid := Invalid;<br>&nbsp; Filters := [moFilename]; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// default filters to moFilename<br>&nbsp; SubTree := true &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // default sub-tree search to on<br>end;<br><br>destructor TDiscMonitor.Destroy;<br>begin<br>&nbsp; FMonitor.Free; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// chuck the thread<br>&nbsp; inherited Destroy<br>end;<br><br>// Change notification from the thread has occurred. Call the component's event<br>// handler and then, if in design mode, and if desired, put up a simple<br>// notification message<br>procedure TDiscMonitor.Change;<br>begin<br>&nbsp; if Assigned (FOnChange) then<br>&nbsp; &nbsp; FOnChange (Self)<br>&nbsp; else<br>&nbsp; &nbsp; if (csDesigning in ComponentState) and FShowMsg then<br>&nbsp; &nbsp; &nbsp; ShowMessage ('Change signalled')<br>end;<br><br>// Invalid notification from the thread has occurred. Call the component's event<br>// handler and then, if in design mode, and if desired, put up a simple<br>// notification message<br>procedure TDiscMonitor.Invalid;<br>begin<br>&nbsp; if Assigned (FOnInvalid) then<br>&nbsp; &nbsp; FOnInvalid (Self)<br>&nbsp; else<br>&nbsp; &nbsp; if (csDesigning in ComponentState) and FShowMsg then<br>&nbsp; &nbsp; &nbsp; ShowMessage ('Invalid parameter signalled')<br>end;<br><br>// Stop the monitor running<br>procedure TDiscMonitor.Close;<br>begin<br>&nbsp; Active := false<br>end;<br><br>// Run the monitor<br>procedure TDiscMonitor.Open;<br>begin<br>&nbsp; Active := true<br>end;<br><br>// Control the thread by using it's resume and suspend methods<br>procedure TDiscMonitor.SetActive (Value : boolean);<br>begin<br>&nbsp; if Value &lt;&gt; FActive then<br>&nbsp; begin<br>&nbsp; &nbsp; FActive := Value;<br>&nbsp; &nbsp; if Active then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; FMonitor.Resume;<br>&nbsp; &nbsp; &nbsp; FMonitor.Update<br>&nbsp; &nbsp; end else<br>&nbsp; &nbsp; &nbsp; FMonitor.Suspend<br>&nbsp; end<br>end;<br><br>// get the current directory from the thread<br>function TDiscMonitor.GetDirectory : TDiscMonitorDirStr;<br>begin<br>&nbsp; Result := FMonitor.Directory<br>end;<br><br>// get the current sub-tree status from the thread<br>function TDiscMonitor.GetSubTree : boolean;<br>begin<br>&nbsp; Result := FMonitor.SubTree<br>end;<br><br>// set the directory to monitor<br>procedure TDiscMonitor.SetDirectory (Value : TDiscMonitorDirStr);<br>begin<br>&nbsp; FMonitor.Directory := Value<br>end;<br><br>// Change the filter conditions. &nbsp;The thread uses the raw windows constants<br>// (FILE_NOTIFY_CHANGE_XXXX) but the components uses a set of enumurated type.<br>// It is therefore necessary to translate from the component format into<br>// an integer value for the thread.<br>procedure TDiscMonitor.SetFilters (Value : TMonitorFilters);<br>const<br>&nbsp; XlatFileNotify : array [moFilename..moSecurity] of integer =<br>&nbsp; &nbsp; (FILE_NOTIFY_CHANGE_FILE_NAME, &nbsp;FILE_NOTIFY_CHANGE_DIR_NAME,<br>&nbsp; &nbsp; &nbsp;FILE_NOTIFY_CHANGE_ATTRIBUTES, FILE_NOTIFY_CHANGE_SIZE,<br>&nbsp; &nbsp; &nbsp;FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_NOTIFY_CHANGE_SECURITY);<br>var<br>&nbsp; L : TMonitorFilter;<br>&nbsp; I : integer;<br>begin<br>&nbsp; if Value &lt;&gt; FFilters then<br>&nbsp; &nbsp; if Value = [] then<br>&nbsp; &nbsp; &nbsp; ShowMessage ('Some filter condition must be set.')<br>&nbsp; &nbsp; else begin<br>&nbsp; &nbsp; &nbsp; FFilters := Value;<br>&nbsp; &nbsp; &nbsp; I := 0;<br>&nbsp; &nbsp; &nbsp; for L := moFilename to moSecurity do<br>&nbsp; &nbsp; &nbsp; &nbsp; if L in Value then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; I := I or XlatFileNotify [L];<br>&nbsp; &nbsp; &nbsp; FMonitor.Filters := I;<br>&nbsp; &nbsp; end<br>end;<br><br>// set the sub-tree status in the thread<br>procedure TDiscMonitor.SetSubTree (Value : boolean);<br>begin<br>&nbsp; FMonitor.SubTree := Value<br>end;<br><br>procedure Register;<br>begin<br>&nbsp; RegisterComponents ('FileSys', [TDiscMonitor]);<br>&nbsp; {RegisterPropertyEditor (TypeInfo (TDiscMonitorDirStr), nil, '', TDiscMonitorDirStrProperty);}<br>end;<br><br>end.<br>另外如果是在NT下面,调用得函数是CreateIOCompletionPort<br>而不是CreateCompletionPort,上次说错了.:)<br>用ReadDirectoryChangesW与上面得方法相似.<br>这是一个外国人的代码.
 
还没有结束吗?<br>嘻嘻,给分把.
 
分我一定会给,不用担心。<br>只是这些天在搞工作单位的事,所以没空玩请原谅。<br>等过些天我会检查这个程序和问题并给分的。
 
张先生的那个控件很好用,我很喜欢。<br>接受答案了,让诸位久等!<br>分数每人至少5分,安慰安慰。 :)
 
后退
顶部