在网上找到一段代码
可以监视系统所有文件的变化,
其中包括 新建,删除,修改文件名,修改目录名,都能很好的监视
但是不能监视到文件的修改
比如一个TXT里的内容是 123  把TXT里的内容修改成321都不能监视到求能监视修改文件的代码原代码如下 
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, shlobj, Activex, StdCtrls;const
SHCNE_RENAMEITEM = $1;
SHCNE_CREATE = $2;
SHCNE_DELETE = $4;
SHCNE_MKDIR = $8;
SHCNE_RMDIR = $10;
SHCNE_MEDIAINSERTED = $20;
SHCNE_MEDIAREMOVED = $40;
SHCNE_DRIVEREMOVED = $80;
SHCNE_DRIVEADD = $100;
SHCNE_NETSHARE = $200;
SHCNE_NETUNSHARE = $400;
SHCNE_ATTRIBUTES = $800;
SHCNE_UPDATEDIR = $1000;
SHCNE_UPDATEITEM = $2000;
SHCNE_SERVERDISCONNECT = $4000;
SHCNE_UPDATEIMAGE = $8000;
SHCNE_DRIVEADDGUI = $10000;
SHCNE_RENAMEFOLDER = $20000;
SHCNE_FREESPACE = $40000;
SHCNE_ASSOCCHANGED = $8000000;
SHCNE_DISKEVENTS = $2381F;
SHCNE_GLOBALEVENTS = $C0581E0;
SHCNE_ALLEVENTS = $7FFFFFFF;
SHCNE_INTERRUPT = $80000000;
SHCNF_IDLIST = 0;
SHCNF_PATHA = $1;
SHCNF_PRINTERA = $2;
SHCNF_DWORD = $3;
SHCNF_PATHW = $5;
SHCNF_PRINTERW = $6;
SHCNF_TYPE = $FF;
SHCNF_FLUSH = $1000;
SHCNF_FLUSHNOWAIT = $2000;
SHCNF_PATH = SHCNF_PATHW;
SHCNF_PRINTER = SHCNF_PRINTERW;
WM_SHNOTIFY = $401;
NOERROR = 0;type
TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
private
    procedure WMShellReg(var Message: TMessage); message WM_SHNOTIFY;
public
    { Public declarations }
end;type
PSHNOTIFYSTRUCT = ^SHNOTIFYSTRUCT;
SHNOTIFYSTRUCT = record
    dwItem1: PItemIDList;
    dwItem2: PItemIDList;
end;
type PSHFileInfoByte = ^SHFileInfoByte;
_SHFileInfoByte = record
    hIcon: Integer;
    iIcon: Integer;
    dwAttributes: Integer;
    szDisplayName: array[0..259] of char;
    szTypeName: array[0..79] of char;
end;
SHFileInfoByte = _SHFileInfoByte;
type PIDLSTRUCT = ^IDLSTRUCT;
_IDLSTRUCT = record
    pidl: PItemIDList;
    bWatchSubFolders: Integer;
end;
IDLSTRUCT = _IDLSTRUCT;
function SHNotify_Register(hWnd: Integer): Bool;
function SHNotify_UnRegister: Bool;
function SHEventName(strPath1, strPath2: string; lParam: Integer): string;
function SHChangeNotifyDeregister(hNotify: Integer): Integer; stdcall;
external 'Shell32.dll' index 4;
function SHChangeNotifyRegister(hWnd, uFlags, dwEventID, uMSG, cItems: LongWord;
lpps: PIDLSTRUCT): Integer; stdcall; external 'Shell32.dll' index 2;
function SHGetFileInfoPidl(pidl: PItemIDList;
dwFileAttributes: Integer;
psfib: PSHFileInfoByte;
cbFileInfo: Integer;
uFlags: Integer): Integer; stdcall;
external 'Shell32.dll' Name 'SHGetFileInfoA';
var
Form1: TForm1;
m_hSHNotify: Integer;
m_pidlDesktop: PItemIDList;implementation{$R *.dfm}function SHEventName(strPath1, strPath2: string; lParam: Integer): string;
var
sEvent: string;
begin
case lParam of //根据参数设置提示消息
    SHCNE_RENAMEITEM: sEvent := '重命名文件' +strPath1+ '为' +strpath2;
    SHCNE_CREATE: sEvent := '建立文件 文件名:' +strPath1;
    SHCNE_DELETE: sEvent := '删除文件 文件名:' +strPath1;
    SHCNE_MKDIR: sEvent := '新建目录 目录名:' +strPath1;
    SHCNE_RMDIR: sEvent := '删除目录 目录名:' +strPath1;
    SHCNE_MEDIAINSERTED: sEvent := strPath1+ '中插入可移动存储介质';
    SHCNE_MEDIAREMOVED: sEvent := strPath1+ '中移去可移动存储介质' +strPath1+ ' ' +strpath2;
    SHCNE_DRIVEREMOVED: sEvent := '移去驱动器' +strPath1;
    SHCNE_DRIVEADD: sEvent := '添加驱动器' +strPath1;
    SHCNE_NETSHARE: sEvent := '改变目录' +strPath1+ '的共享属性';
    SHCNE_ATTRIBUTES: sEvent := '改变文件目录属性 文件名' +strPath1;
    SHCNE_UPDATEDIR: sEvent := '更新目录' +strPath1;
    SHCNE_UPDATEITEM: sEvent := '更新文件 文件名:' +strPath1;
    SHCNE_SERVERDISCONNECT: sEvent := '断开与服务器的连接' +strPath1+ ' ' +strpath2;
    SHCNE_UPDATEIMAGE: sEvent := 'SHCNE_UPDATEIMAGE';
    SHCNE_DRIVEADDGUI: sEvent := 'SHCNE_DRIVEADDGUI';
    SHCNE_RENAMEFOLDER: sEvent := '重命名文件夹' +strPath1+ '为' +strpath2;
    SHCNE_FREESPACE: sEvent := '磁盘空间大小改变';
    SHCNE_ASSOCCHANGED: sEvent := '改变文件关联';
else
    sEvent := '未知操作' +IntToStr(lParam);
end;
Result := sEvent;
end;function SHNotify_Register(hWnd: Integer): Bool;
var
ps: PIDLSTRUCT;
begin
{$R-}
Result := False;
New(ps);
if m_hSHNotify = 0 then begin
//获取桌面文件夹的Pidl
    if SHGetSpecialFolderLocation(0, CSIDL_DESKTOP,
      m_pidlDesktop) <> NOERROR then
      Form1.close;
    if Boolean(m_pidlDesktop) then begin
      ps.bWatchSubFolders := 1;
      ps.pidl := m_pidlDesktop;
// 利用SHChangeNotifyRegister函数注册系统消息处理
      m_hSHNotify := SHChangeNotifyRegister(hWnd, (SHCNF_TYPE or SHCNF_IDLIST),
        (SHCNE_ALLEVENTS or SHCNE_INTERRUPT),
        WM_SHNOTIFY, 1, ps);
      Result := Boolean(m_hSHNotify);
    end
    else
// 如果出现错误就使用 CoTaskMemFree函数来释放句柄
      CoTaskMemFree(m_pidlDesktop);
end;
{$R+}
end;
function SHNotify_UnRegister: Bool;
begin
Result := False;
if Boolean(m_hSHNotify) then
//取消系统消息监视,同时释放桌面的Pidl
    if Boolean(SHChangeNotifyDeregister(m_hSHNotify)) then begin
{$R-}
      m_hSHNotify := 0;
      CoTaskMemFree(m_pidlDesktop);
      Result := True;
{$R-}
    end;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.Caption := '打开监视';
end;procedure TForm1.WMShellReg(var Message: TMessage);
var
strPath1, strPath2: string;
charPath: array[0..259] of char;
pidlItem: PSHNOTIFYSTRUCT;
begin
pidlItem := PSHNOTIFYSTRUCT(Message.wParam);
   //获得系统消息相关得路径
SHGetPathFromIDList(pidlItem.dwItem1, charPath);
strPath1 := charPath;
SHGetPathFromIDList(pidlItem.dwItem2, charPath);
strPath2 := charPath;
Memo1.Lines.Add(SHEventName(strPath1, strPath2, Message.lParam)+chr(13)+chr(10));
end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
//在程序退出的同时删除监视
if Boolean(m_pidlDesktop) then
    SHNotify_UnRegister;
end;procedure TForm1.Button1Click(Sender: TObject); //Button1的Click消息
begin
m_hSHNotify := 0;
if SHNotify_Register(Form1.Handle) then begin //注册Shell监视
    ShowMessage('Shell监视程序成功注册');
    Button1.Enabled := False;
end
else
    ShowMessage('Shell监视程序注册失败');
end;end.

解决方案 »

  1.   

    要用ReadDirectoryChanges方法,具体代码我有
      

  2.   


    求代码  [email protected]   谢谢
      

  3.   

    CNVCL 有开源监视文件组件,灰常好用。
      

  4.   

    楼主给分吧unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, ExtCtrls, Buttons;type
      TForm1 = class(TForm)
        lbEvents: TListBox;
        Label1: TLabel;
        ePath: TEdit;
        CJLabel1: TLabel;
        bStart: TButton;
        bStop: TButton;
        ckWatchSubTree: TCheckBox;
        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
        FDirectoryHandle: THandle;
        FNotificationBuffer: array[0..4096] of Byte;
        FWatchThread: TThread;
        FNotifyFilter: DWORD;
        FOverlapped: TOverlapped;
        FPOverlapped: POverlapped;
        FBytesWritten: DWORD;
        FCompletionPort: THandle;
      public
      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 =
      ( '增加-> %s',
        '删除-> %s',
        '访问-> %s',
        '改名-> %s [...]',
        '[...] 改为 %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;
      s:Array[1..127] of char; i:DWord;
    begin
      Getcomputername(@s,i);
      with FForm do
      begin
        Pointer(FileOpNotification) := @FNotificationBuffer[0];
        repeat
          Offset := FileOpNotification^.NextEntryOffset;
          lbEvents.Items.Add(Format(SAction[FileOpNotification^.Action], [WideCharToString(@(FileOpNotification^.FileName))])+s);
          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(请选择监视内容!');
         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
      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.
      

  5.   


    支持ReadDirectoryChanges的方法......