delphi监控文件夹

(******************************************
  文件和目录监控
  当磁盘上有文件或目录操作时,产生事件
  使用方法:

  开始监控: PathWatch(Self.Handle, 'C:\FtpFolder');
  解除监控:PathWatch(-1);

  在窗体中加消息监听
  private
    { Private declarations }
    procedure MsgListern(var Msg:TMessage);message WM_SHNOTIFY;

  实现:
  procedure TForm1.MsgListern(var Msg:TMessage);
  begin
    PathWatch(Msg,procedure(a,s1,s2:String) begin
      Log('文件事件是:'  +a);
      Log('文件名称是:'  +s1);
      Log('另外的参数是:'+s2);
    end);
  end;

******************************************)
unit PathWatch;

interface

uses
  Winapi.Messages, System.SysUtils, FMX.Types, FMX.Platform.Win, WinAPI.ShlObj,
  Winapi.ActiveX, WinApi.Windows, VCL.Dialogs
  ;

const
  WM_SHNOTIFY = $401;

type
  PIDLSTRUCT = ^IDLSTRUCT;
  _IDLSTRUCT = record
    pidl : PItemIDList;
    bWatchSubFolders : Integer;
  end;
  IDLSTRUCT =_IDLSTRUCT;
type
  PSHNOTIFYSTRUCT=^SHNOTIFYSTRUCT;
  SHNOTIFYSTRUCT = record
    dwItem1 : PItemIDList;
    dwItem2 : PItemIDList;
  end;

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 PathWatch(hWND: Integer      ; Path:String=''):Boolean; overload;
function PathWatch(hWND: TWindowHandle; Path:String=''):Boolean; overload;
function PathWatch(var Msg: TMessage; callback: TProc<String,String,String>):Boolean; overload;

var
  g_HSHNotify   : Integer;
  g_pidlDesktop : PItemIDList;
  g_WatchPath   : String;

implementation

function PathWatch(hWND: Integer; Path:String=''):Boolean;
var
  ps:PIDLSTRUCT;
begin
  result:=False;
  Path:=Path.Replace('/','\');
  if(hWnd>=0) then begin  //  开始监控
    g_WatchPath:=Path.ToUpper;

    if g_HSHNotify = 0 then begin
      SHGetSpecialFolderLocation(0, CSIDL_DESKTOP, g_pidlDesktop);
      if Boolean(g_pidlDesktop) then begin
        getmem(ps,sizeof(IDLSTRUCT));
        ps.bWatchSubFolders := 1;
        ps.pidl := g_pidlDesktop;
        g_HSHNotify := SHChangeNotifyRegister(hWnd, (SHCNF_TYPE Or SHCNF_IDLIST),(SHCNE_ALLEVENTS Or SHCNE_INTERRUPT),WM_SHNOTIFY, 1, ps);
        Result := Boolean(g_HSHNotify);
      end else CoTaskMemFree(g_pidlDesktop);
    end;
  end else begin  //  解除监控
    if boolean(g_HSHNotify) then if Boolean(SHChangeNotifyDeregister(g_HSHNotify)) then begin
      g_HSHNotify := 1;
      CoTaskMemFree(g_pidlDesktop);
      result := True;
    end;
  end;
end;

function PathWatch(hWND: TWindowHandle; Path:String=''):Boolean;
begin
  PathWatch(FmxHandleToHWND(hWND),Path);  //  FireMonkey的窗体不接受处理Windows消息
end;

function PathWatch(var Msg: TMessage; callback:TProc<String,String,String>):Boolean;
var
  a, s1,s2  : String;
  buf       : array[0..MAX_PATH] of char;
  pidlItem  : PSHNOTIFYSTRUCT;
begin
  pidlItem :=PSHNOTIFYSTRUCT(Msg.WParam);
  SHGetPathFromIDList(pidlItem.dwItem1, buf); s1 := buf;
  SHGetPathFromIDList(pidlItem.dwItem2, buf); s2 := buf;
  a:='';
  case Msg.LParam of
//    SHCNE_RENAMEITEM      : a := '重命名'       ;
    SHCNE_CREATE          : a := '建立文件'     ;
//    SHCNE_DELETE          : a := '删除文件'     ;
//    SHCNE_MKDIR           : a := '新建目录'     ;
//    SHCNE_RMDIR           : a := '删除目录'     ;
//    SHCNE_ATTRIBUTES      : a := '改变属性'     ;
//    SHCNE_MEDIAINSERTED   : a := '插入介质'     ;
//    SHCNE_MEDIAREMOVED    : a := '移去介质'     ;
//    SHCNE_DRIVEREMOVED    : a := '移去驱动器'   ;
//    SHCNE_DRIVEADD        : a := '添加驱动器'   ;
//    SHCNE_NETSHARE        : a := '改变共享'     ;
//    SHCNE_UPDATEDIR       : a := '更新目录'     ;
//    SHCNE_UPDATEITEM      : a := '更新文件'     ;
//    SHCNE_SERVERDISCONNECT: a := '断开连接'     ;
//    SHCNE_UPDATEIMAGE     : a := '更新图标'     ;
//    SHCNE_DRIVEADDGUI     : a := '添加驱动器'   ;
//    SHCNE_RENAMEFOLDER    : a := '重命名文件夹' ;
//    SHCNE_FREESPACE       : a := '磁盘空间改变' ;
//    SHCNE_ASSOCCHANGED    : a := '改变文件关联' ;
//  else                      a := '其他操作'     ;

  end;
  result := True;
  if( (a<>'') and (Assigned(callback)) and (s1.ToUpper.StartsWith(g_WatchPath))) and (not s1.Contains('_plate')) then
  begin
    callback(a,s1,g_WatchPath);
  end;
end;


end.

 调用:

PathWatch(self.Handle, DM.Config.O['Local'].S['PhotoPath']);

窗体中需要消息事件触发:

procedure MsgListern(var Msg: TMessage); message WM_SHNOTIFY;     // 触发监听事件

procedure TFormMain.MsgListern(var Msg: TMessage);
begin
  PathWatch(Msg, Procedure(act,fn,s2: string) begin
    if(act='建立文件') then begin
      if SecondsBetween(now(), PrePostTime) >= 5 then    //两个时间之间相差的秒数
      begin
       // 这里处理监控到后   要响应的事情
      end;
    end;
  end);
end;

 

posted @ 2015-10-19 09:27  王云盼  阅读(1644)  评论(0编辑  收藏  举报