T tianhf Unregistered / Unconfirmed GUEST, unregistred user! 2001-11-29 #2 {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *<br><br>Component: TDirMon<br>Description: This component encapsulate the Win 32 API function<br> FindFirstChangeNotification. The primary purpose of this component<br> is to monitor changes in a given directory and fire an event<br> when a change occurs (file creation, deletion, ...).<br>Version: 1.00<br>Created: March 27, 1997<br>Author: Fran&ccedil;ois PIETTE<br>Email: francois.piette@ping.be http://www.rtfm.be/fpiette<br> francois.piette@f2202.n293.z2.fidonet.org<br> 2:293/2202@fidonet.org, BBS +32-4-3651395<br>Support: Please ask your question in the following newsgroup:<br> news://forums.borland.com/borland.public.delphi.vcl.components.using<br>Legal issues: Copyright (C) 1997 by Fran&ccedil;ois PIETTE <francois.piette@ping.be><br><br> This software is provided 'as-is', without any express or<br> implied warranty. In no event will the author be held liable<br> for any damages arising from the use of this software.<br><br> Permission is granted to anyone to use this software for any<br> purpose, including commercial applications, and to alter it<br> and redistribute it freely, subject to the following<br> restrictions:<br><br> 1. The origin of this software must not be misrepresented,<br> you must not claim that you wrote the original software.<br> If you use this software in a product, an acknowledgment <br> in the product documentation would be appreciated but is<br> not required.<br><br> 2. Altered source versions must be plainly marked as such, and <br> must not be misrepresented as being the original software.<br><br> 3. This notice may not be removed or altered from any source <br> distribution.<br><br>Modification History:<br>Aug 07, 1997 V1.0 Added some comments<br><br><br> * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>unit DirMon;<br><br>interface<br><br>uses<br> Windows,<br> SysUtils,<br> Messages,<br> Classes,<br> Graphics,<br> Controls,<br> Forms,<br> Dialogs,<br> Menus;<br><br>const<br> WM_DIRCHANGE= WM_USER + 1;<br><br>type<br> TDirMonValue = (dmcFileName,<br> dmcDirName,<br> dmcAttributes,<br> dmcSize,<br> dmcLastWrite,<br> dmcSecurity);<br> TDirMonType = set of TDirMonValue;<br><br> TDirMon = class(TComponent)<br> private<br> FDirectory : String;<br> FNotifyFilter : DWORD;<br> FWindowHandle : HWND;<br> FParamPtr : Pointer;<br> FMutexHandle : THandle;<br> FThreadHandle : THandle;<br> FThreadID : DWORD;<br> FOnDirChange : TNotifyEvent;<br> FOnStart : TNotifyEvent;<br> FOnStop : TNotifyEvent;<br> procedure WndProc(var MsgRec: TMessage);<br> procedure WMDirChange(var aMsg: TMessage); message WM_DIRCHANGE;<br> protected<br> procedure SetNotifyFilter(newValue : TDirMonType);<br> function GetNotifyFilter : TDirMonType;<br> procedure SetDirectory(newValue : String);<br> procedure TriggerDirChangeEvent; virtual;<br> procedure TriggerStartEvent; virtual;<br> procedure TriggerStopEvent; virtual;<br> public<br> constructor Create(AOwner : TComponent); override;<br> destructor Destroy; override;<br> procedure Start;<br> procedure Stop;<br> published<br> { Published properties and events }<br> property Directory : String read FDirectory<br> write SetDirectory;<br> property NotifyFilter : TDirMonType read GetNotifyFilter<br> write SetNotifyFilter;<br> property OnDirChange : TNotifyEvent read FOnDirChange<br> write FOnDirChange;<br> property Handle : HWND read FWindowHandle;<br> property OnStart : TNotifyEvent read FOnStart write FOnStart;<br> property OnStop : TNotifyEvent read FOnStop write FOnStop;<br> end;<br><br>procedure Register;<br><br>implementation<br><br>type<br> TDirMonParams = record<br> WindowHandle : HWND;<br> hMutex : THandle;<br> Directory : array [0..255] of char;<br> NotifyFilter : DWORD;<br> end;<br> PDirMonParams = ^TDirMonParams;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure Register;<br>begin<br> RegisterComponents('FPiette', [TDirMon]);<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.SetDirectory(newValue : String);<br>begin<br> if newValue = FDirectory then<br> Exit;<br><br> if FThreadHandle <> 0 then<br> raise Exception.Create('Unable to change Directory ' +<br> 'when DirMon is running');<br><br> FDirectory := newValue;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.SetNotifyFilter(newValue : TDirMonType);<br>begin<br> if FThreadHandle <> 0 then<br> raise Exception.Create('Unable to change NotifyFilter ' +<br> 'when DirMon is running');<br><br> FNotifyFilter := 0;<br> if dmcFileName in newValue then<br> FNotifyFilter := (FNotifyFilter or FILE_NOTIFY_CHANGE_FILE_NAME);<br> if dmcDirName in newValue then<br> FNotifyFilter := (FNotifyFilter or FILE_NOTIFY_CHANGE_DIR_NAME);<br> if dmcAttributes in newValue then<br> FNotifyFilter := (FNotifyFilter or FILE_NOTIFY_CHANGE_ATTRIBUTES);<br> if dmcSize in newValue then<br> FNotifyFilter := (FNotifyFilter or FILE_NOTIFY_CHANGE_SIZE);<br> if dmcLastWrite in newValue then<br> FNotifyFilter := (FNotifyFilter or FILE_NOTIFY_CHANGE_LAST_WRITE);<br> if dmcSecurity in newValue then<br> FNotifyFilter := (FNotifyFilter or FILE_NOTIFY_CHANGE_SECURITY);<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>function TDirMon.GetNotifyFilter : TDirMonType;<br>begin<br> Result := [];<br> if (FNotifyFilter and FILE_NOTIFY_CHANGE_FILE_NAME) <> 0 then<br> Result := Result + [dmcFileName];<br> if (FNotifyFilter and FILE_NOTIFY_CHANGE_DIR_NAME) <> 0 then<br> Result := Result + [dmcDirName];<br> if (FNotifyFilter and FILE_NOTIFY_CHANGE_ATTRIBUTES) <> 0 then<br> Result := Result + [dmcAttributes];<br> if (FNotifyFilter and FILE_NOTIFY_CHANGE_SIZE) <> 0 then<br> Result := Result + [dmcSize];<br> if (FNotifyFilter and FILE_NOTIFY_CHANGE_LAST_WRITE) <> 0 then<br> Result := Result + [dmcLastWrite];<br> if (FNotifyFilter and FILE_NOTIFY_CHANGE_SECURITY) <> 0 then<br> Result := Result + [dmcSecurity];<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.TriggerDirChangeEvent;<br>begin<br> if assigned(FOnDirChange) then begin<br> try<br> FOnDirChange(Self);<br> except<br> end;<br> end;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.TriggerStartEvent;<br>begin<br> if assigned(FOnStart) then<br> FOnStart(Self);<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.TriggerStopEvent;<br>begin<br> if assigned(FOnStop) then<br> FOnStop(Self);<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>constructor TDirMon.Create(AOwner : TComponent);<br>begin<br> inherited Create(AOwner);<br> FWindowHandle := AllocateHWnd(WndProc);<br> FNotifyFilter := FILE_NOTIFY_CHANGE_FILE_NAME;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>destructor TDirMon.Destroy;<br>begin<br> if FThreadHandle <> 0 then begin<br> ReleaseMutex(FMutexHandle);<br> WaitForSingleObject(FThreadHandle, INFINITE);<br> end;<br><br> if FParamPtr <> nil then begin<br> FreeMem(FParamPtr);<br> FParamPtr := nil;<br> end;<br><br> if FMutexHandle <> 0 then begin<br> CloseHandle(FMutexHandle);<br> FMutexHandle := 0;<br> end;<br><br> DeallocateHWnd(FWindowHandle);<br> inherited Destroy;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.WndProc(var MsgRec: TMessage);<br>begin<br> with MsgRec do begin<br> if Msg = WM_DIRCHANGE then<br> WMDirChange(MsgRec)<br> else<br> Result := DefWindowProc(Handle, Msg, wParam, lParam);<br> end;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.WMDirChange(var aMsg: TMessage);<br>begin<br> TriggerDirChangeEvent;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>function MonitorThread(Prm : Pointer) : DWORD; stdcall;<br>var<br> Hdl : THandle;<br> Status : DWORD;<br> pParams : PDirMonParams;<br> hObjects : array [0..1] of THandle;<br>begin<br> if Prm = nil then<br> ExitThread(1);<br><br> pParams := PDirMonParams(Prm);<br><br> Hdl := FindFirstChangeNotification(pParams^.Directory,<br> FALSE,<br> pParams^.NotifyFilter);<br> if Hdl = INVALID_HANDLE_VALUE then begin<br> Application.MessageBox('FindFirstChangeNotification() failed',<br> 'Warning', mb_OK);<br> ExitThread(GetLastError);<br> end;<br><br> while (TRUE) do begin<br> hObjects[0] := Hdl;<br> hObjects[1] := pParams.hMutex;<br> Status := WaitForMultipleObjects(2, @hObjects, FALSE, INFINITE);<br><br> if Status = WAIT_OBJECT_0 then begin<br> PostMessage(pParams^.WindowHandle, WM_DIRCHANGE, 0, 0);<br><br> if not FindNextChangeNotification(Hdl) then begin<br> FindCloseChangeNotification(Hdl);<br> ExitThread(GetLastError);<br> end;<br> end;<br><br> if Status = (WAIT_OBJECT_0 + 1) then begin<br> FindCloseChangeNotification(Hdl);<br> ReleaseMutex(pParams.hMutex);<br> ExitThread(0);<br> end;<br> end;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.Start;<br>var<br> p : PDirMonParams;<br>begin<br> if FThreadHandle <> 0 then<br> raise Exception.Create('DirMon already started');<br><br> // Create mutex for stopping thread when needed<br> FMutexHandle := CreateMutex(nil, TRUE, nil);<br> if FMutexHandle = 0 then<br> raise Exception.Create('CreateMutex failed');<br><br> // Allocate some memory for thread parameters<br> GetMem(p, SizeOf(TDirMonParams));<br> FParamPtr := p;<br> p^.WindowHandle := FWindowHandle;<br> p^.hMutex := FMutexHandle;<br> p^.NotifyFilter := FNotifyFilter;<br> StrCopy(p^.Directory, PChar(FDirectory));<br><br> // Start the working thread<br> FThreadHandle := CreateThread(<br> nil, // pointer to thread security attributes<br> 0, // initial thread stack size, in bytes<br> @MonitorThread, // pointer to thread function<br> FParamPtr, // argument for new thread<br> 0, // creation flags<br> FThreadId); // pointer to returned thread identifier<br><br> if FThreadHandle = 0 then<br> raise Exception.Create('CreateThread failed');<br><br> TriggerStartEvent;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.Stop;<br>begin<br> if FThreadHandle = 0 then<br> raise Exception.Create('DirMon not started');<br><br> if FMutexHandle <> 0 then<br> ReleaseMutex(FMutexHandle);<br><br> if FThreadHandle <> 0 then begin<br> WaitForSingleObject(FThreadHandle, INFINITE);<br> FThreadHandle := 0;<br> FThreadID := 0;<br> end;<br><br> if FMutexHandle <> 0 then begin<br> CloseHandle(FMutexHandle);<br> FMutexHandle := 0;<br> end;<br><br> if FParamPtr <> nil then begin<br> FreeMem(FParamPtr);<br> FParamPtr := nil;<br> end;<br><br> TriggerStopEvent;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br><br>end.<br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *<br><br>Component: TDirMon<br>Description: This component encapsulate the Win 32 API function<br> FindFirstChangeNotification. The primary purpose of this component<br> is to monitor changes in a given directory and fire an event<br> when a change occurs (file creation, deletion, ...).<br>Version: 1.00<br>Created: March 27, 1997<br>Author: Fran&ccedil;ois PIETTE<br>Email: francois.piette@ping.be http://www.rtfm.be/fpiette<br> francois.piette@f2202.n293.z2.fidonet.org<br> 2:293/2202@fidonet.org, BBS +32-4-3651395<br>Support: Please ask your question in the following newsgroup:<br> news://forums.borland.com/borland.public.delphi.vcl.components.using<br>Legal issues: Copyright (C) 1997 by Fran&ccedil;ois PIETTE <francois.piette@ping.be><br><br> This software is provided 'as-is', without any express or<br> implied warranty. In no event will the author be held liable<br> for any damages arising from the use of this software.<br><br> Permission is granted to anyone to use this software for any<br> purpose, including commercial applications, and to alter it<br> and redistribute it freely, subject to the following<br> restrictions:<br><br> 1. The origin of this software must not be misrepresented,<br> you must not claim that you wrote the original software.<br> If you use this software in a product, an acknowledgment <br> in the product documentation would be appreciated but is<br> not required.<br><br> 2. Altered source versions must be plainly marked as such, and <br> must not be misrepresented as being the original software.<br><br> 3. This notice may not be removed or altered from any source <br> distribution.<br><br>Modification History:<br>Aug 07, 1997 V1.0 Added some comments<br><br><br> * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>unit DirMon;<br><br>interface<br><br>uses<br> Windows,<br> SysUtils,<br> Messages,<br> Classes,<br> Graphics,<br> Controls,<br> Forms,<br> Dialogs,<br> Menus;<br><br>const<br> WM_DIRCHANGE= WM_USER + 1;<br><br>type<br> TDirMonValue = (dmcFileName,<br> dmcDirName,<br> dmcAttributes,<br> dmcSize,<br> dmcLastWrite,<br> dmcSecurity);<br> TDirMonType = set of TDirMonValue;<br><br> TDirMon = class(TComponent)<br> private<br> FDirectory : String;<br> FNotifyFilter : DWORD;<br> FWindowHandle : HWND;<br> FParamPtr : Pointer;<br> FMutexHandle : THandle;<br> FThreadHandle : THandle;<br> FThreadID : DWORD;<br> FOnDirChange : TNotifyEvent;<br> FOnStart : TNotifyEvent;<br> FOnStop : TNotifyEvent;<br> procedure WndProc(var MsgRec: TMessage);<br> procedure WMDirChange(var aMsg: TMessage); message WM_DIRCHANGE;<br> protected<br> procedure SetNotifyFilter(newValue : TDirMonType);<br> function GetNotifyFilter : TDirMonType;<br> procedure SetDirectory(newValue : String);<br> procedure TriggerDirChangeEvent; virtual;<br> procedure TriggerStartEvent; virtual;<br> procedure TriggerStopEvent; virtual;<br> public<br> constructor Create(AOwner : TComponent); override;<br> destructor Destroy; override;<br> procedure Start;<br> procedure Stop;<br> published<br> { Published properties and events }<br> property Directory : String read FDirectory<br> write SetDirectory;<br> property NotifyFilter : TDirMonType read GetNotifyFilter<br> write SetNotifyFilter;<br> property OnDirChange : TNotifyEvent read FOnDirChange<br> write FOnDirChange;<br> property Handle : HWND read FWindowHandle;<br> property OnStart : TNotifyEvent read FOnStart write FOnStart;<br> property OnStop : TNotifyEvent read FOnStop write FOnStop;<br> end;<br><br>procedure Register;<br><br>implementation<br><br>type<br> TDirMonParams = record<br> WindowHandle : HWND;<br> hMutex : THandle;<br> Directory : array [0..255] of char;<br> NotifyFilter : DWORD;<br> end;<br> PDirMonParams = ^TDirMonParams;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure Register;<br>begin<br> RegisterComponents('FPiette', [TDirMon]);<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.SetDirectory(newValue : String);<br>begin<br> if newValue = FDirectory then<br> Exit;<br><br> if FThreadHandle <> 0 then<br> raise Exception.Create('Unable to change Directory ' +<br> 'when DirMon is running');<br><br> FDirectory := newValue;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.SetNotifyFilter(newValue : TDirMonType);<br>begin<br> if FThreadHandle <> 0 then<br> raise Exception.Create('Unable to change NotifyFilter ' +<br> 'when DirMon is running');<br><br> FNotifyFilter := 0;<br> if dmcFileName in newValue then<br> FNotifyFilter := (FNotifyFilter or FILE_NOTIFY_CHANGE_FILE_NAME);<br> if dmcDirName in newValue then<br> FNotifyFilter := (FNotifyFilter or FILE_NOTIFY_CHANGE_DIR_NAME);<br> if dmcAttributes in newValue then<br> FNotifyFilter := (FNotifyFilter or FILE_NOTIFY_CHANGE_ATTRIBUTES);<br> if dmcSize in newValue then<br> FNotifyFilter := (FNotifyFilter or FILE_NOTIFY_CHANGE_SIZE);<br> if dmcLastWrite in newValue then<br> FNotifyFilter := (FNotifyFilter or FILE_NOTIFY_CHANGE_LAST_WRITE);<br> if dmcSecurity in newValue then<br> FNotifyFilter := (FNotifyFilter or FILE_NOTIFY_CHANGE_SECURITY);<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>function TDirMon.GetNotifyFilter : TDirMonType;<br>begin<br> Result := [];<br> if (FNotifyFilter and FILE_NOTIFY_CHANGE_FILE_NAME) <> 0 then<br> Result := Result + [dmcFileName];<br> if (FNotifyFilter and FILE_NOTIFY_CHANGE_DIR_NAME) <> 0 then<br> Result := Result + [dmcDirName];<br> if (FNotifyFilter and FILE_NOTIFY_CHANGE_ATTRIBUTES) <> 0 then<br> Result := Result + [dmcAttributes];<br> if (FNotifyFilter and FILE_NOTIFY_CHANGE_SIZE) <> 0 then<br> Result := Result + [dmcSize];<br> if (FNotifyFilter and FILE_NOTIFY_CHANGE_LAST_WRITE) <> 0 then<br> Result := Result + [dmcLastWrite];<br> if (FNotifyFilter and FILE_NOTIFY_CHANGE_SECURITY) <> 0 then<br> Result := Result + [dmcSecurity];<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.TriggerDirChangeEvent;<br>begin<br> if assigned(FOnDirChange) then begin<br> try<br> FOnDirChange(Self);<br> except<br> end;<br> end;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.TriggerStartEvent;<br>begin<br> if assigned(FOnStart) then<br> FOnStart(Self);<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.TriggerStopEvent;<br>begin<br> if assigned(FOnStop) then<br> FOnStop(Self);<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>constructor TDirMon.Create(AOwner : TComponent);<br>begin<br> inherited Create(AOwner);<br> FWindowHandle := AllocateHWnd(WndProc);<br> FNotifyFilter := FILE_NOTIFY_CHANGE_FILE_NAME;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>destructor TDirMon.Destroy;<br>begin<br> if FThreadHandle <> 0 then begin<br> ReleaseMutex(FMutexHandle);<br> WaitForSingleObject(FThreadHandle, INFINITE);<br> end;<br><br> if FParamPtr <> nil then begin<br> FreeMem(FParamPtr);<br> FParamPtr := nil;<br> end;<br><br> if FMutexHandle <> 0 then begin<br> CloseHandle(FMutexHandle);<br> FMutexHandle := 0;<br> end;<br><br> DeallocateHWnd(FWindowHandle);<br> inherited Destroy;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.WndProc(var MsgRec: TMessage);<br>begin<br> with MsgRec do begin<br> if Msg = WM_DIRCHANGE then<br> WMDirChange(MsgRec)<br> else<br> Result := DefWindowProc(Handle, Msg, wParam, lParam);<br> end;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.WMDirChange(var aMsg: TMessage);<br>begin<br> TriggerDirChangeEvent;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>function MonitorThread(Prm : Pointer) : DWORD; stdcall;<br>var<br> Hdl : THandle;<br> Status : DWORD;<br> pParams : PDirMonParams;<br> hObjects : array [0..1] of THandle;<br>begin<br> if Prm = nil then<br> ExitThread(1);<br><br> pParams := PDirMonParams(Prm);<br><br> Hdl := FindFirstChangeNotification(pParams^.Directory,<br> FALSE,<br> pParams^.NotifyFilter);<br> if Hdl = INVALID_HANDLE_VALUE then begin<br> Application.MessageBox('FindFirstChangeNotification() failed',<br> 'Warning', mb_OK);<br> ExitThread(GetLastError);<br> end;<br><br> while (TRUE) do begin<br> hObjects[0] := Hdl;<br> hObjects[1] := pParams.hMutex;<br> Status := WaitForMultipleObjects(2, @hObjects, FALSE, INFINITE);<br><br> if Status = WAIT_OBJECT_0 then begin<br> PostMessage(pParams^.WindowHandle, WM_DIRCHANGE, 0, 0);<br><br> if not FindNextChangeNotification(Hdl) then begin<br> FindCloseChangeNotification(Hdl);<br> ExitThread(GetLastError);<br> end;<br> end;<br><br> if Status = (WAIT_OBJECT_0 + 1) then begin<br> FindCloseChangeNotification(Hdl);<br> ReleaseMutex(pParams.hMutex);<br> ExitThread(0);<br> end;<br> end;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.Start;<br>var<br> p : PDirMonParams;<br>begin<br> if FThreadHandle <> 0 then<br> raise Exception.Create('DirMon already started');<br><br> // Create mutex for stopping thread when needed<br> FMutexHandle := CreateMutex(nil, TRUE, nil);<br> if FMutexHandle = 0 then<br> raise Exception.Create('CreateMutex failed');<br><br> // Allocate some memory for thread parameters<br> GetMem(p, SizeOf(TDirMonParams));<br> FParamPtr := p;<br> p^.WindowHandle := FWindowHandle;<br> p^.hMutex := FMutexHandle;<br> p^.NotifyFilter := FNotifyFilter;<br> StrCopy(p^.Directory, PChar(FDirectory));<br><br> // Start the working thread<br> FThreadHandle := CreateThread(<br> nil, // pointer to thread security attributes<br> 0, // initial thread stack size, in bytes<br> @MonitorThread, // pointer to thread function<br> FParamPtr, // argument for new thread<br> 0, // creation flags<br> FThreadId); // pointer to returned thread identifier<br><br> if FThreadHandle = 0 then<br> raise Exception.Create('CreateThread failed');<br><br> TriggerStartEvent;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>procedure TDirMon.Stop;<br>begin<br> if FThreadHandle = 0 then<br> raise Exception.Create('DirMon not started');<br><br> if FMutexHandle <> 0 then<br> ReleaseMutex(FMutexHandle);<br><br> if FThreadHandle <> 0 then begin<br> WaitForSingleObject(FThreadHandle, INFINITE);<br> FThreadHandle := 0;<br> FThreadID := 0;<br> end;<br><br> if FMutexHandle <> 0 then begin<br> CloseHandle(FMutexHandle);<br> FMutexHandle := 0;<br> end;<br><br> if FParamPtr <> nil then begin<br> FreeMem(FParamPtr);<br> FParamPtr := nil;<br> end;<br><br> TriggerStopEvent;<br>end;<br><br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br><br>end.<br><br>{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}<br>