unit UnitFolderMonitor;

interface

uses Windows, Classes, SysUtils, Messages, VCL.Dialogs;

type TFolderMonitorThread = class(TThread)
    private
        h : THandle;
        folder : string;
        fOnChange : TNotifyEvent;

    public
        procedure Execute; override;
end;


type TFolderMonitor = class(TObject)
    private
        folder : string;
        thread : TFolderMonitorThread;
        fOnChange : TNotifyEvent;

    public
        procedure SetFolder(f : string);
        procedure Cancel;
    property
        OnChange :  TNotifyEvent read fOnChange write fOnChange;

end;


var FolderMonitor : TFolderMonitor;

implementation

uses UnitMisc, UnitFrmDebug;

procedure TFolderMonitor.SetFolder(f : string);
begin
    f := IncludeTrailingBackslash(f);
    if (f <> '') then begin
        // kill thread and re-create each time

        if thread <> nil then begin
            thread.Terminate;
            thread.Free;
        end;
        thread := TFolderMonitorThread.Create(True);
        thread.folder := f;
        self.folder := f;
        thread.fOnChange := self.fOnChange;

        thread.Start;
    end;

end;
procedure TFolderMonitor.Cancel;
begin
    if thread <> nil then
        self.thread.Terminate;
end;


procedure TFolderMonitorThread.Execute;
var c : Cardinal;
    i : integer;
begin
    FrmDebug.AppendLog('FolderMonitor: start');
    h := INVALID_HANDLE_VALUE;
    i := 0;
    while (h = INVALID_HANDLE_VALUE) do begin
        h := FindFirstChangeNotification(
            pchar(folder),
            false,
            FILE_NOTIFY_CHANGE_ATTRIBUTES or FILE_NOTIFY_CHANGE_FILE_NAME or
            FILE_NOTIFY_CHANGE_LAST_WRITE or FILE_NOTIFY_CHANGE_CREATION
        );
        inc(i);
        if (i=10) then BREAK;
        mysleep(100);
    end;

    if (h = INVALID_HANDLE_VALUE) then begin
        FrmDebug.AppendLog('FolderMonitor: Unable to monitor folder');
    end else begin
        repeat
            c := WaitForSingleObject(h, 1000);
        until (c <> WAIT_TIMEOUT) or self.Terminated;

        FindCloseChangeNotification(h);

        if not self.Terminated then begin
            if assigned(fOnChange) then begin
                fOnChange(nil);
            end;
        end;
        h := 0;
    end;
end;

initialization
begin

end;

end.
