unit TextFileProcessu;

interface

uses
  Classes, mainformu, Windows, SysUtils, StrUtils;

type
  TTextFileProcessor = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

implementation

function IsFileInUse(fName : string) : boolean; forward;

{ TTextFileProcessor }

procedure TTextFileProcessor.Execute;
var
  HDirChange: THandle;
  WaitResult: Cardinal;
  sr: TSearchRec;
  ObjHandles : Array[0..1] of THandle;
begin
  HDirChange := FindFirstChangeNotification(
    PChar(AppDir),
    False, FILE_NOTIFY_CHANGE_FILE_NAME);
  ObjHandles[0] := HDirChange;
  ObjHandles[1] := Event.Handle;     //requires SyncObjs
  while True do
  begin

    WaitResult := WaitForMultipleObjects(2, @ObjHandles, False, INFINITE);
    if WaitResult = 0 then  //the file notification was detected. Process files
//  WaitResult := WaitForSingleObject(HDirChange, INFINITE);
//  if WaitResult = WAIT_OBJECT_0 then  //the file notification was detected. Process files
    begin
      if SysUtils.FindFirst('*.txt', faAnyFile, sr) = 0 then
      begin
        //Do not attempt to load the file until it is available
        while IsFileInUse(AppDir + sr.Name) do
          continue;
        repeat
          //There is a race condition here. If the file becomes in use
          //before the LoadFromFile is executed in the LoadTextFile
          //method, an exception will occur.
          Self.Synchronize(procedure
                           begin
                             LoadTextFile(AppDir + sr.Name);
                           end);
        until FindNext(sr) <> 0;
        FindClose(sr);
      end;
    end;
    if Terminated then Exit;
    FindNextChangeNotification(HDirChange);
  end;
end;



/// This code was published by Zarko Gajic on Delphi.About.Com
function IsFileInUse(fName : string) : boolean;
 var
   HFileRes : HFILE;
   Res: string[6];

   function CheckAttributes(FileNam: string; CheckAttr: string): Boolean;
   var
     fa: Integer;
   begin
     fa := GetFileAttributes(PChar(FileNam)) ;
     Res := '';
     if (fa and FILE_ATTRIBUTE_NORMAL) <> 0 then
     begin
       Result := False;
       Exit;
     end;
     if (fa and FILE_ATTRIBUTE_ARCHIVE) <> 0 then
       Res := Res + 'A';
     if (fa and FILE_ATTRIBUTE_COMPRESSED) <> 0 then
       Res := Res + 'C';
     if (fa and FILE_ATTRIBUTE_DIRECTORY) <> 0 then
       Res := Res + 'D';
     if (fa and FILE_ATTRIBUTE_HIDDEN) <> 0 then
       Res := Res + 'H';
     if (fa and FILE_ATTRIBUTE_READONLY) <> 0 then
       Res := Res + 'R';
     if (fa and FILE_ATTRIBUTE_SYSTEM) <> 0 then
       Res := Res + 'S';
     Result := AnsiContainsText(Res, CheckAttr) ;
   end; (*CheckAttributes*)

   procedure SetAttr(fName: string) ;
   var
     Attr: Integer;
   begin
     Attr := 0;
     if AnsiContainsText(Res, 'A') then
       Attr := Attr + FILE_ATTRIBUTE_ARCHIVE;
     if AnsiContainsText(Res, 'C') then
       Attr := Attr + FILE_ATTRIBUTE_COMPRESSED;
     if AnsiContainsText(Res, 'D') then
       Attr := Attr + FILE_ATTRIBUTE_DIRECTORY;
     if AnsiContainsText(Res, 'H') then
       Attr := Attr + FILE_ATTRIBUTE_HIDDEN;
     if AnsiContainsText(Res, 'S') then
       Attr := Attr + FILE_ATTRIBUTE_SYSTEM;
     SetFileAttributes(PChar(fName), Attr);
   end; (*SetAttr*)

begin //IsFileInUse
  if CheckAttributes(fName, 'R') then
  begin
    Result := False;
    if not FileExists(fName) then exit;
    Result := True;
    Exit;
  end;

  SetFileAttributes(PChar(fName), FILE_ATTRIBUTE_NORMAL) ;
  SetAttr(fName) ;
  HFileRes := CreateFile(pchar(fName), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) ;
  Result := (HFileRes = INVALID_HANDLE_VALUE) ;
  CloseHandle(HFileRes);
end; //IsFileInUse


end.
