8 MaxDirsChange
= MAXIMUM_WAIT_OBJECTS
;
11 TOnDirectoryChange
= procedure( Sender
: PObj
; const Path
: String ) of object;
13 PMultiDirsChange
= ^TMultiDirsChange
;
14 TMultiDirsChange
= object( TObj
)
16 FOnChange
: TOnDirectoryChange
;
18 function GetPaths( Index
: Integer ): String;
19 procedure SetPaths( Index
: Integer; const Value
: String);
21 FPaths
: array[ 0..MaxDirsChange
-1 ] of String;
22 FHandles
: array[ 0..MaxDirsChange
-1 ] of THandle
;
26 procedure Init
; virtual;
27 function ExecuteThread( Sender
: PThread
): Integer;
29 procedure FolderChanged( Sender
: PThread
; P
: Pointer );
31 property Paths
[ Idx
: Integer ]: String read GetPaths write SetPaths
;
32 destructor Destroy
; virtual;
33 function Active
: Boolean;
34 function PathsMonitored
: Integer;
38 function NewMultiDirChange( OnChange
: TOnDirectoryChange
; Filter
: DWORD
): PMultiDirsChange
;
41 PAnyDirsChange
= ^TAnyDirsChange
;
42 TAnyDirsChange
= object( TObj
)
46 FOnChange
: TOnDirectoryChange
;
48 function GetCount
: Integer;
49 function GetPaths(Idx
: Integer): String;
50 procedure FolderChanged( Sender
: PObj
; const Path
: String );
51 procedure Init
; virtual;
53 destructor Destroy
; virtual;
54 property Paths
[ Idx
: Integer ]: String read GetPaths
;
55 property Count
: Integer read GetCount
;
56 procedure Add( const Path
: String );
57 procedure Remove( const Path
: String ); overload
;
58 procedure Remove( Idx
: Integer ); overload
;
62 function NewAnyDirsChange( OnChange
: TOnDirectoryChange
; Filter
: DWORD
): PAnyDirsChange
;
66 function NewMultiDirChange( OnChange
: TOnDirectoryChange
; Filter
: DWORD
): PMultiDirsChange
;
68 new( Result
, Create
);
69 Result
.FOnChange
:= OnChange
;
71 Filter
:= FILE_NOTIFY_CHANGE_FILE_NAME
or FILE_NOTIFY_CHANGE_DIR_NAME
or
72 FILE_NOTIFY_CHANGE_ATTRIBUTES
or FILE_NOTIFY_CHANGE_SIZE
or
73 FILE_NOTIFY_CHANGE_LAST_WRITE
;
74 Result
.FFilter
:= Filter
;
77 function NewAnyDirsChange( OnChange
: TOnDirectoryChange
; Filter
: DWORD
): PAnyDirsChange
;
79 new( Result
, Create
);
80 Result
.FOnChange
:= OnChange
;
82 Filter
:= FILE_NOTIFY_CHANGE_FILE_NAME
or FILE_NOTIFY_CHANGE_DIR_NAME
or
83 FILE_NOTIFY_CHANGE_ATTRIBUTES
or FILE_NOTIFY_CHANGE_SIZE
or
84 FILE_NOTIFY_CHANGE_LAST_WRITE
;
85 Result
.FFilter
:= Filter
;
90 function TMultiDirsChange
.Active
: Boolean;
92 Result
:= FThread
<> nil;
95 procedure TMultiDirsChange
.Clear
;
100 procedure TMultiDirsChange
.CloseQuied
;
102 while FDelHandles
.Count
> 0 do
104 FindCloseChangeNotification( THandle( FDelHandles
.Items
[ 0 ] ) );
105 FDelHandles
.Delete( 0 );
109 destructor TMultiDirsChange
.Destroy
;
118 function TMultiDirsChange
.ExecuteThread( Sender
: PThread
): Integer;
119 var WaitHandles
: array[ 0..MaxDirsChange
-1 ] of THandle
;
124 while (PathsMonitored
> 0) and (Applet
<> nil) and not AppletTerminated
do
127 for I
:= 0 to High( FPaths
) do
129 if FHandles
[ I
] <> 0 then
131 WaitHandles
[ N
] := FHandles
[ I
];
137 R
:= WaitForMultipleObjects( N
, @ WaitHandles
[ 0 ], FALSE, 100 );
138 if (R
>= WAIT_OBJECT_0
) and (R
< WAIT_OBJECT_0
+ N
) then
140 for I
:= 0 to High( FHandles
) do
141 if FHandles
[ I
] = WaitHandles
[ R
- WAIT_OBJECT_0
] then
143 if (Applet
<> nil) and not AppletTerminated
then
145 if Assigned( FOnChange
) then
146 Sender
.SynchronizeEx( FolderChanged
, @ I
);
147 FindNextChangeNotification( FHandles
[ I
] );
159 procedure TMultiDirsChange
.FolderChanged(Sender
: PThread
; P
: Pointer);
163 if (I
>= 0) and (I
< MaxDirsChange
) and Assigned( FOnChange
) then
164 FOnChange( @ Self
, FPaths
[ I
] );
167 function TMultiDirsChange
.GetPaths( Index
: Integer ): String;
169 Result
:= FPaths
[ Index
];
172 procedure TMultiDirsChange
.Init
;
174 FDelHandles
:= NewList
;
177 function TMultiDirsChange
.PathsMonitored
: Integer;
181 for I
:= 0 to High( FPaths
) do
182 if FPaths
[ I
] <> '' then Inc(Result
);
185 procedure TMultiDirsChange
.SetPaths( Index
: Integer; const Value
: String);
187 FPaths
[ Index
] := Value
;
188 if FHandles
[ Index
] <> 0 then
189 FDelHandles
.Add( Pointer( FHandles
[ Index
] ) );
190 FHandles
[ Index
] := 0;
193 FHandles
[ Index
] := FindFirstChangeNotification( PChar( FPaths
[ Index
] ),
196 if (FThread
<> nil) and FThread
.Terminated
then
197 Free_And_Nil( FThread
);
198 if (FThread
= nil) and (PathsMonitored
> 0) then
200 FThread
:= NewThread
;
201 FThread
.OnExecute
:= ExecuteThread
;
208 procedure TAnyDirsChange
.Add(const Path
: String);
209 var I
, J
, E
: Integer;
210 D
, D0
: PMultiDirsChange
;
214 for I
:= 0 to FNotifiers
.Count
-1 do
216 D
:= FNotifiers
.Items
[ I
];
217 for J
:= 0 to MaxDirsChange
-1 do
218 if AnsiEq( D
.Paths
[ J
], Path
) then
219 Exit
// íå íàäî äîáàâëÿòü - óæå åñòü òàêàÿ
221 if (D0
= nil) and (D
.Paths
[ J
] = '') then
229 D0
:= NewMultiDirChange( FolderChanged
, FFilter
);
230 FNotifiers
.Add( D0
);
232 FDirs
.AddObject( Path
, DWORD( D0
) );
233 D0
.Paths
[ E
] := Path
;
236 function TAnyDirsChange
.GetCount
: Integer;
238 Result
:= FDirs
.Count
;
241 function TAnyDirsChange
.GetPaths(Idx
: Integer): String;
243 Result
:= FDirs
.Items
[ Idx
];
246 procedure TAnyDirsChange
.Remove(const Path
: String);
249 I
:= FDirs
.IndexOf( Path
);
254 procedure TAnyDirsChange
.Init
;
256 FDirs
:= NewStrListEx
;
257 FNotifiers
:= NewList
;
260 procedure TAnyDirsChange
.Remove(Idx
: Integer);
261 var D
: PMultiDirsChange
;
264 D
:= Pointer( FDirs
.Objects
[ Idx
] );
265 for I
:= 0 to MaxDirsChange
-1 do
266 if AnsiEq( D
.Paths
[ I
], FDirs
.Items
[ Idx
] ) then
273 destructor TAnyDirsChange
.Destroy
;
276 FNotifiers
.ReleaseObjects
;
280 procedure TAnyDirsChange
.FolderChanged(Sender
: PObj
; const Path
: String);
285 for I
:= 0 to FDirs
.Count
-1 do
286 if AnsiEq( FDirs
.Items
[ I
], Path
) then
288 found
:= TRUE; break
;
290 if not found
then Exit
;
291 if Assigned( FOnChange
) then
292 FOnChange( @ Self
, Path
);
295 procedure TAnyDirsChange
.Clear
;
299 for I
:= 0 to FNotifiers
.Count
-1 do
301 D
:= FNotifiers
.Items
[ I
];