unit notification; //{$DEFINE DEBUG} //{$DEFINE MULTIPLE} interface uses Classes, Windows, myWStrings; type T_UpdateFile = record sFileName: WideString; rWriteTime: TFileTime; end; P_UpdateFile = ^T_UpdateFile; TMyChangeNotification = class(TThread) private { Private 宣言 } {$IFDEF MULTIPLE} F_hHandles: TWOHandleArray; F_slDir: TMyWStrings; F_slList: TList; {$ELSE} F_hHandle: THandle; F_sFileName: WideString; F_rFileTime: TFileTime; {$ENDIF} F_rConfirmTime: TFileTime; procedure UpdateText; protected procedure Execute; override; public {$IFDEF MULTIPLE} constructor Create(slList: TMyWStrings); {$ELSE} // constructor Create(slList: TMyWStrings); constructor Create(sFileName: WideString); {$ENDIF} destructor Destroy; override; end; implementation uses {$IFDEF DEBUG} myDebug, {$ENDIF} Forms, SysUtils, myFile, myFileStrings, myList, main; { TMyChangeNotification } {$IFDEF MULTIPLE} constructor TMyChangeNotification.Create(slList: TMyWStrings); var i: Integer; ls_Dir: WideString; lsl_Files: TMyWStrings; lp_Item: P_UpdateFile; {$ELSE} //constructor TMyChangeNotification.Create(slList: TMyWStrings); constructor TMyChangeNotification.Create(sFileName: WideString); {$ENDIF} begin {$IFDEF MULTIPLE} F_slList := TList.Create; F_slDir := TMyFileStrings.Create; lsl_Files := TMyFileStrings.Create; try lsl_Files.Assign(slList); lsl_Files.FileInsertionSort(True); //ソートして重複を削除 TMyFileStrings(lsl_Files).UpperCase; ls_Dir := #1; //あり得ないフォルダ名にしておく for i := 0 to lsl_Files.Count -1 do begin if (gfnsFilePathGet(lsl_Files[i]) <> ls_Dir) then begin ls_Dir := gfnsFilePathGet(lsl_Files[i]); F_slDir.Add(ls_Dir); F_hHandles[i] := FindFirstChangeNotificationW( PWideChar(ls_Dir), False, FILE_NOTIFY_CHANGE_LAST_WRITE or FILE_NOTIFY_CHANGE_SIZE ); end; New(lp_Item); FillChar(lp_Item^, SizeOf(lp_Item^), 0); lp_Item^.sFileName := WideUpperCase(slList[i]); lp_Item^.rWriteTime := gfnrFileWriteTimeGet(slList[i]); F_slList.Add(lp_Item); end; TMyFileStrings(F_slDir).UpperCase; finally lsl_Files.Free; end; {$ELSE} // F_sFileName := slList[slList.Count -1]; F_sFileName := sFileName; F_rFileTime := gfnrFileWriteTimeGet(F_sFileName); F_hHandle := FindFirstChangeNotificationW( PWideChar(gfnsFileDirGet(F_sFileName)), False, FILE_NOTIFY_CHANGE_LAST_WRITE ); {$ENDIF} inherited Create(False); end; destructor TMyChangeNotification.Destroy; {$IFDEF MULTIPLE} var i: Integer; {$ENDIF} begin Terminate; {$IFDEF MULTIPLE} for i := 0 to F_slList.Count -1 do begin if (F_hHandles[i] <> 0) then begin FindCloseChangeNotification(F_hHandles[i]); F_hHandles[i] := 0; end; end; gpcListFree(F_slList); F_slDir.Free; {$ELSE} if (F_hHandle <> 0) then begin FindCloseChangeNotification(F_hHandle); F_hHandle := 0; end; {$ENDIF} inherited; end; procedure TMyChangeNotification.Execute; {$IFDEF MULTIPLE} var i: Integer; li_Index: DWORD; lr_Item: T_UpdateFile; {$ENDIF} begin // try while not(Terminated) do begin {$IFDEF MULTIPLE} li_Index := WaitForMultipleObjects(F_slDir.Count, @F_hHandles, False, INFINITE) - WAIT_OBJECT_0; if (li_Index < DWORD(F_slDir.Count)) then begin for i := 0 to F_slList.Count -1 do begin lr_Item := T_UpdateFile(F_slList[i]^); if (gfnsFilePathGet(lr_Item.sFileName) = F_slDir[li_Index]) then begin F_rConfirmTime := gfnrFileWriteTimeGet(lr_Item.sFileName); if (F_rConfirmTime.dwLowDateTime <> lr_Item.rWriteTime.dwLowDateTime) or (F_rConfirmTime.dwHighDateTime <> lr_Item.rWriteTime.dwHighDateTime) then begin Synchronize(UpdateText); lr_Item.rWriteTime.dwLowDateTime := F_rConfirmTime.dwLowDateTime; lr_Item.rWriteTime.dwHighDateTime := F_rConfirmTime.dwHighDateTime; FindNextChangeNotification(F_hHandles[li_Index]); Break; end; end; end; end; {$ELSE} if (WaitForSingleObject(F_hHandle, INFINITE) = WAIT_OBJECT_0) then begin F_rConfirmTime := gfnrFileWriteTimeGet(F_sFileName); if ((F_rConfirmTime.dwLowDateTime <> 0) and (F_rConfirmTime.dwHighDateTime <> 0)) and ((F_rConfirmTime.dwLowDateTime <> F_rFileTime.dwLowDateTime) or (F_rConfirmTime.dwHighDateTime <> F_rFileTime.dwHighDateTime)) then begin { myDebug.gpcDebug([F_rFileTime.dwLowDateTime, F_rFileTime.dwHighDateTime, F_rConfirmTime.dwLowDateTime, F_rConfirmTime.dwHighDateTime, F_sFileName ]); } Synchronize(UpdateText); F_rFileTime.dwLowDateTime := F_rConfirmTime.dwLowDateTime; F_rFileTime.dwHighDateTime := F_rConfirmTime.dwHighDateTime; end; end; FindNextChangeNotification(F_hHandle); {$ENDIF} Sleep(1); //これがないとCPU使用率が天井に張り付く end; // finally // if (F_hHandle <> 0) then begin // FindCloseChangeNotification(F_hHandle); // F_hHandle := 0; // end; // end; end; procedure TMyChangeNotification.UpdateText; begin if (Terminated) or (Application.Terminated) then Exit; App_sPad.SetFileUpdate; end; end.