(************************************************************************
*    This File is Part of the AHM Triton Tools                          *
*    for Borland Delphi and C++ Builder.                                *
*************************************************************************
* Copyright © 1995-1999 Alexander H. Mehlhorn (AHM) and Tritontools.com *
* All Rights reserved.                                                  *
*                                                                       *
*    For more Information contact us at                                 *
*    E-Mail : support@tritontools.com                                   *
*    URL : http://www.tritontools.com                                   *
*                                                                       *
*    AHM is copyright by Alexander H. Mehlhorn                          *
*    All Parts of this Collection were developed,                       *
*    designed and implemented by AHM                                    *
*                                                                       *
*    Under no Circumstances may you distribute this file                *
*    in this or any other format. This File is supplied                 *
*    as Evaluation of Source only. No Delphi Components may be developed*
*    using extracts or subsets of this code without expressed permission*
*    by AHM.                                                            *
*                                                                       *
*************************************************************************)
unit AHMTDiskMonitor;
interface
uses
  Windows, Messages, SysUtils, Classes,AHMSystemClass,AHMSystemConst;
type
  TAHMMonitorType = (monFiles,monDirectories,monAttributes,monSize,monLastWrite,monSecurity);
  TAHMMonitorSet = Set of TAHMMonitorType;
  TAHMDiskLocation = class;
  TAHMChangeThread = class(TThread)
    OwnerTimer: TAHMDiskLocation;
    Procedure Execute; override;
    Procedure DoTimer;
  end;
  TAHMDiskMonitor = class;
  TAHMDiskLocations = class;
  TAHMDiskLocation = class(TCollectionItem)
  private
    FEnabled: Boolean;
    FMonType : Dword;
    FChangeThread: TAHMChangeThread;
    FThreadPriority: TThreadPriority;
    FAHMDiskMonitor : TAHMDiskMonitor;
    FOnChangeOccured: TNotifyevent;
    FLocation: String;
    FEvents: TAHMMonitorSet;
    FSubDirectory: Boolean;
    Procedure SetEnabled(Const Value: Boolean);
    Procedure SetThreadPriority(Const Value: TThreadPriority);
    procedure SetLocation(const Value: String);
    procedure SetEvents(const Value: TAHMMonitorSet);
    procedure SetSubDirectory(const Value: Boolean);
  protected
    function GetDisplayName: string; override;
    Procedure UpdateTimer;
  public
    constructor Create(Collection: TCollection); override;
    procedure Assign(Source: TPersistent); override;
    property Owner : TAHMDiskMonitor read FAHMDiskMonitor;
    property DisplayName : String read GetDisplayName;
    destructor Destroy; override;
  published
    Property OnChangeOccured : TNotifyevent read FOnChangeOccured write FOnChangeOccured;
    Property Location : String read FLocation write SetLocation;
    Property Enabled: Boolean read FEnabled write SetEnabled default True;
    Property Events : TAHMMonitorSet read FEvents write SetEvents default [];
    Property SubDirectory : Boolean read FSubDirectory write SetSubDirectory default False; 
    Property Priority: TThreadPriority read FThreadPriority write SetThreadPriority default tpNormal;
  end;
  TAHMDiskLocations = class(TCollection)
  private
    FAHMDiskMonitor : TAHMDiskMonitor;
    function GetAHMDiskLocation(Index: Integer): TAHMDiskLocation;
    procedure SetAHMDiskLocation(Index: Integer; Value: TAHMDiskLocation);
  protected
    function GetOwner : TPersistent; override;
  public
    constructor Create(AOwner: TAHMDiskMonitor);
    function Add : TAHMDiskLocation;
    function Delete(Index :Integer) :Boolean;
    property Owner : TAHMDiskMonitor read FAHMDiskMonitor;
    property Items[Index: Integer]: TAHMDiskLocation read GetAHMDiskLocation write SetAHMDiskLocation; default;
  end;
  TAHMDiskMonitor = class(TAHMSystemsComponent)
  private
    FAHMDiskLocations : TAHMDiskLocations;
    procedure SetAHMDiskLocations(Value: TAHMDiskLocations);
  protected
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Locations: TAHMDiskLocations read FAHMDiskLocations write SetAHMDiskLocations;
  end;

implementation

uses Forms;

Procedure TAHMChangeThread.Execute;
var
  TempArr : array [0..Max_Path-1] of char;
  AHandle : THandle;
begin
  Priority := OwnerTimer.FThreadPriority;
  FillChar(TempArr,SizeOf(TempArr),0);
  AHandle := FindFirstChangeNotification (StrPCopy(TempArr,PChar(OwnerTimer.FLocation)),OwnerTimer.FSubDirectory,OwnerTimer.FMonType);
  while (not Terminated) do
  begin
     WaitForSingleObject (AHandle, INFINITE);
     if Assigned(OwnerTimer.OnChangeOccured) then Synchronize(DoTimer);
     FindNextChangeNotification (AHandle);
  end;
  FindCloseChangeNotification(AHandle);
end;

Procedure TAHMChangeThread.DoTimer;
begin
  if assigned(OwnerTimer.FOnChangeOccured) then OwnerTimer.FOnChangeOccured(Self);
end;

constructor TAHMDiskLocation.Create(Collection: TCollection);
begin
  inherited Create(Collection);
  FAHMDiskMonitor :=(((Collection as TAHMDiskLocations).GetOwner) as TAHMDiskMonitor);
  FEnabled := True;
  FMonType:=0;
  FSubDirectory:=False;
  FEvents:=[];
  FThreadPriority := tpNormal;
  FChangeThread := TAHMChangeThread.Create(false);
  FChangeThread.OwnerTimer := Self;
  UpdateTimer;
end;

destructor TAHMDiskLocation.Destroy;
begin
  FEnabled := False;
  UpdateTimer;
  FChangeThread.Free;
  inherited Destroy;
end;

Procedure TAHMDiskLocation.UpdateTimer;
begin
  if not(FChangeThread.Suspended) then FChangeThread.Suspend;
  if not(csDesigning in FAHMDiskMonitor.Componentstate) then
  if FEnabled and assigned(FOnChangeOccured) and (FLocation<>'') and (FEvents<>[]) then
  if (FChangeThread.Suspended) then  FChangeThread.Resume;
end;

function LocationExists(const Name: string): Boolean;
var
  Code: Integer;
begin
  Code := GetFileAttributes(PChar(Name));
  Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
end;

procedure TAHMDiskLocation.SetLocation(const Value: String);
begin
  if (Value <> FLocation) and (LocationExists(Value)) then FLocation := Value;
  UpdateTimer;
end;

Procedure TAHMDiskLocation.SetEnabled(Const Value: Boolean);
begin
  if Value <> FEnabled then FEnabled := Value;
  UpdateTimer;
end;

Procedure TAHMDiskLocation.SetThreadPriority(Const Value: TThreadPriority);
begin
  if Value <> FThreadPriority then FThreadPriority := Value;
  UpdateTimer;
end;

function TAHMDiskLocation.GetDisplayName: string;
begin
  if (FLocation<>'') and FEnabled and (FEvents<>[]) then
  Result := ahmscmonitor1+FLocation+ahmscmonitor2 else
  Result := ahmscmonitor3;
end;

function TAHMDiskLocations.GetOwner: TPersistent;
begin
  Result := FAHMDiskMonitor;
end;

constructor TAHMDiskLocations.Create(AOwner: TAHMDiskMonitor);
begin
  inherited Create(TAHMDiskLocation);
  FAHMDiskMonitor := AOwner;
end;

function TAHMDiskLocations.Add: TAHMDiskLocation;
begin
  Result := TAHMDiskLocation(inherited Add);
end;

function TAHMDiskLocations.GetAHMDiskLocation(Index: Integer): TAHMDiskLocation;
begin
  Result := TAHMDiskLocation(inherited GetItem(Index));
end;

procedure TAHMDiskLocations.SetAHMDiskLocation(Index: Integer; Value: TAHMDiskLocation);
begin
  inherited SetItem(Index, Value);
end;

constructor TAHMDiskMonitor.Create(AOwner: TComponent);
begin
  inherited create(AOwner);
  FAHMDiskLocations:=TAHMDiskLocations.Create(self);
end;

destructor TAHMDiskMonitor.Destroy;
begin
  FAHMDiskLocations.Free;
  inherited Destroy;
end;

procedure TAHMDiskMonitor.SetAHMDiskLocations(Value: TAHMDiskLocations);
begin
  FAHMDiskLocations.Assign(Value);
end;


function TAHMDiskLocations.Delete(Index: Integer): Boolean;
begin
  result := true;
  Try
    Items[Index].free;
  Except
    result := false;
    Application.handleexception(self);
  End;
end;

procedure TAHMDiskLocation.Assign(Source: TPersistent);
begin
  if Source is TAHMDiskLocation then
  begin
    Enabled  := TAHMDiskLocation(Source).Enabled;
    OnChangeOccured  := TAHMDiskLocation(Source).OnChangeOccured;
    Priority := TAHMDiskLocation(Source).Priority;
    Location := TAHMDiskLocation(Source).Location;
    SubDirectory:=TAHMDiskLocation(Source).SubDirectory;
    SetEvents(TAHMDiskLocation(Source).FEvents);
    Exit;
  end;
  inherited Assign(Source);
end;


procedure TAHMDiskLocation.SetEvents(const Value: TAHMMonitorSet);
begin
  FEvents := Value;
  FMonType:=0;
  if (monFiles in Value)  then FMonType := FMonType or FILE_NOTIFY_CHANGE_FILE_NAME;
  if (monDirectories in Value)   then FMonType := FMonType or FILE_NOTIFY_CHANGE_DIR_NAME;
  if (monAttributes in Value) then FMonType := FMonType or FILE_NOTIFY_CHANGE_ATTRIBUTES;
  if (monSize in Value)       then FMonType := FMonType or FILE_NOTIFY_CHANGE_SIZE;
  if (monLastWrite in Value) then FMonType := FMonType or FILE_NOTIFY_CHANGE_LAST_WRITE;
  if (monSecurity in Value)   then FMonType := FMonType or FILE_NOTIFY_CHANGE_SECURITY;
  UpdateTimer;
end;

procedure TAHMDiskLocation.SetSubDirectory(const Value: Boolean);
begin
  FSubDirectory := Value;
  UpdateTimer;
end;

end.
