以下是DELPHI的例子:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, Buttons;
type
TForm1 = class(TForm)
lbEvents: TListBox;
Panel1: TPanel;
Label1: TLabel;
ePath: TEdit;
CJLabel1: TLabel;
bStart: TButton;
bStop: TButton;
ckWatchSubTree: TCheckBox;
GroupBox1: TGroupBox;
ckMonitorFileName: TCheckBox;
ckMonitorDirName: TCheckBox;
ckMonitorAttributes: TCheckBox;
ckMonitorSize: TCheckBox;
ckMonitorLastWrite: TCheckBox;
ckMonitorSecurity: TCheckBox;
ckMonitorCreationDate: TCheckBox;
ckMonitorLastAccess: TCheckBox;
SpeedButton1: TSpeedButton;
procedure bStartClick(Sender: TObject);
procedure bStopClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ePathDblClick(Sender: TObject);
private
{ D閏larations priv閑s }
FDirectoryHandle: THandle;
FNotificationBuffer: array[0..4096] of Byte;
FWatchThread: TThread;
FNotifyFilter: DWORD;
FOverlapped: TOverlapped;
FPOverlapped: POverlapped;
FBytesWritten: DWORD;
FCompletionPort: THandle;
public
{ D閏larations publiques }
end;
var
Form1: TForm1;
type
PFileNotifyInformation = ^TFileNotifyInformation;
TFileNotifyInformation = record
NextEntryOffset: DWORD;
Action: DWORD;
FileNameLength: DWORD;
FileName: array[0..0] of WideChar;
end;
const
FILE_LIST_DIRECTORY = $0001;
const
SAction: array[FILE_ACTION_ADDED..FILE_ACTION_RENAMED_NEW_NAME] of String =
( 'ADDED %s',
'DELETED %s',
'MODIFIED %s',
'RENAMED %s [...]',
'[...] into %s');
implementation
{$R *.DFM}
uses
ShlObj, ActiveX;
type
TWaitThread = class(TThread)
private
FForm: TForm1;
procedure HandleEvent;
protected
procedure Execute; override;
public
constructor Create(Form: TForm1);
end;
constructor TWaitThread.Create(Form: TForm1);
begin
inherited Create(True);
FForm := Form;
FreeOnTerminate := False;
end;
procedure TWaitThread.HandleEvent;
var
FileOpNotification: PFileNotifyInformation;
Offset: Longint;
begin
with FForm do
begin
Pointer(FileOpNotification) := @FNotificationBuffer[0];
repeat
Offset := FileOpNotification^.NextEntryOffset;
lbEvents.Items.Add(Format(SAction[FileOpNotification^.Action], [WideCharToString(@(FileOpNotification^.FileName))]));
PChar(FileOpNotification) := PChar(FileOpNotification)+Offset;
until Offset=0;
end;
end;
procedure TWaitThread.Execute;
var
numBytes: DWORD;
cbOffset: DWORD;
CompletionKey: DWORD;
begin
while not Terminated do
begin
GetQueuedCompletionStatus( FForm.FCompletionPort, numBytes, CompletionKey, FForm.FPOverlapped, INFINITE);
if CompletionKey <> 0 then
begin
Synchronize(HandleEvent);
with FForm do
begin
FBytesWritten := 0;
ZeroMemory(@FNotificationBuffer, SizeOf(FNotificationBuffer));
ReadDirectoryChanges(FDirectoryHandle, @FNotificationBuffer, SizeOf(FNotificationBuffer), ckWatchSubTree.Checked, FNotifyFilter, @FBytesWritten, @FOverlapped, nil);
end;
end
else
Terminate;
end;
end;
procedure TForm1.bStartClick(Sender: TObject);
begin
FNotifyFilter := 0;
if ckMonitorFileName.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_FILE_NAME;
if ckMonitorDirName.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_DIR_NAME;
if ckMonitorAttributes.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_ATTRIBUTES;
if ckMonitorSize.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_SIZE;
if ckMonitorLastWrite.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_LAST_WRITE;
if ckMonitorLastAccess.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_LAST_ACCESS;
if ckMonitorCreationDate.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_CREATION;
if ckMonitorSecurity.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_SECURITY;
if FNotifyFilter = 0 then
begin
ShowMessage('Vous devez monitorer au moins 1 関閚ement !');
exit;
end;
lbEvents.Clear;
FDirectoryHandle := CreateFile(PChar(ePath.Text),
FILE_LIST_DIRECTORY,
FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
nil,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED,
0);
if FDirectoryHandle = INVALID_HANDLE_VALUE then
begin
beep;
FDirectoryHandle := 0;
ShowMessage(SysErrorMessage(GetLastError));
exit;
end;
FCompletionPort := CreateIoCompletionPort(FDirectoryHandle, 0, Longint(pointer(self)), 0);
ZeroMemory(@FNotificationBuffer, SizeOf(FNotificationBuffer));
FBytesWritten := 0;
if not ReadDirectoryChanges(FDirectoryHandle, @FNotificationBuffer, SizeOf(FNotificationBuffer), ckWatchSubTree.Checked, FNotifyFilter, @FBytesWritten, @FOverlapped, nil) then
begin
CloseHandle(FDirectoryHandle);
FDirectoryHandle := 0;
CloseHandle(FCompletionPort);
FCompletionPort := 0;
ShowMessage(SysErrorMessage(GetLastError));
exit;
end;
ePath.Enabled := False;
bStart.Enabled := False;
bStop.Enabled := True;
FWatchThread := TWaitThread.Create(self);
TWaitThread(FWatchThread).Resume;
end;
procedure TForm1.bStopClick(Sender: TObject);
begin
if FCompletionPort = 0 then
exit;
PostQueuedCompletionStatus(FCompletionPort, 0, 0, nil);
FWatchThread.WaitFor;
FWatchThread.Free;
CloseHandle(FDirectoryHandle);
FDirectoryHandle := 0;
CloseHandle(FCompletionPort);
FCompletionPort := 0;
ePath.Enabled := True;
bStart.Enabled := True;
bStop.Enabled := False;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
bStop.Click;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FCompletionPort := 0;
FDirectoryHandle := 0;
FPOverlapped := @FOverlapped;
ZeroMemory(@FOverlapped, SizeOf(FOverlapped));
end;
procedure TForm1.ePathDblClick(Sender: TObject);
var
SelectionPIDL: PItemIDList;
BrowseInfo: TBrowseInfo;
ShellAllocator: IMalloc;
PathBuffer: array[0..MAX_PATH] of Char;
begin
// simplest implementation of BrowseForFolder
// to get more information refer to MSDN Library or Check Brad Stower's excellent site www.delphifreestuff.com
ZeroMemory(@BrowseInfo, SizeOf(BrowseInfo));
BrowseInfo.hwndOwner := Handle;
BrowseInfo.ulFlags := BIF_RETURNONLYFSDIRS;
CoInitialize(nil);
try
SelectionPIDL := ShBrowseForFolder(BrowseInfo);
if SelectionPIDL <> nil then
try
ZeroMemory(@PathBuffer, SizeOf(PathBuffer));
if not SHGetPathFromIDList(SelectionPIDL, @PathBuffer) then
begin
beep;
exit;
end;
ePath.Text := StrPas(@PathBuffer[0]);
finally
if SHGetMalloc(ShellAllocator) = 0 then
begin
ShellAllocator.Free(SelectionPIDL);
ShellAllocator := nil;
end;
end;
finally
CoUnInitialize;
end;
end;
end.