⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jvchangenotify.pas

📁 East make Tray Icon in delphi
💻 PAS
📖 第 1 页 / 共 2 页
字号:
begin
  Result := TJvChangeItem(inherited GetItem(Index));
end;

procedure TJvChangeItems.SetItem(Index: Integer; Value: TJvChangeItem);
begin
  inherited SetItem(Index, Value);
end;

function TJvChangeItems.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

procedure TJvChangeItems.Assign(Source: TPersistent);
var
  I: Integer;
begin
  if Source is TJvChangeItems then
  begin
    Clear;
    for I := 0 to TJvChangeItems(Source).Count - 1 do
      Add.Assign(TJvChangeItems(Source)[I]);
  end
  else
    inherited Assign(Source);
end;

//=== { TJvChangeNotify } ====================================================

constructor TJvChangeNotify.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FCollection := TJvChangeItems.Create(Self);
  FActive := False;
  FInterval := 100;
  FFreeOnTerminate := True;
end;

destructor TJvChangeNotify.Destroy;
begin
  Active := False;
  FCollection.Free;
  inherited Destroy;
end;

procedure TJvChangeNotify.CheckActive(const Name: string);
begin
  if Active and
     not ((csDesigning in ComponentState) or (csLoading in ComponentState)) then   //active is now published
    raise EJVCLException.CreateResFmt(@RsEFmtCannotChangeName, [Name]);
end;

procedure TJvChangeNotify.SetCollection(const Value: TJvChangeItems);
begin
  FCollection.Assign(Value);
end;

procedure TJvChangeNotify.Change(Item: TJvChangeItem);
begin
  if Assigned(Item) then
  begin
    Item.Change;
    if Assigned(FNotify) then
      FNotify(Self, Item.Directory, Item.Actions);
  end;
end;

procedure TJvChangeNotify.SetInterval(const Value: Integer);
begin
  CheckActive('Interval');
  if Value <= 0 then
    Exit;
  if FInterval <> Value then
    FInterval := Value;
end;

function TJvChangeNotify.NotifyError(const Msg: string): string;
begin
  SetLength(Result, 256);
  SetLength(Result, FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nil,
    GetLastError, 0, PChar(Result), Length(Result), nil));
  raise EJVCLException.CreateResFmt(@RsENotifyErrorFmt, [Result, Msg]);
end;

procedure TJvChangeNotify.DoThreadChangeNotify(Sender: TObject; Index: Integer);
begin
  Change(Notifications[Index]);
end;

procedure TJvChangeNotify.DoThreadTerminate(Sender: TObject);
begin
  if FreeOnTerminate then
    FThread := nil;
end;

procedure TJvChangeNotify.SetActive(const Value: Boolean);
const
  cActions: array [TJvChangeAction] of Cardinal =
   (FILE_NOTIFY_CHANGE_FILE_NAME, FILE_NOTIFY_CHANGE_DIR_NAME,
    FILE_NOTIFY_CHANGE_ATTRIBUTES, FILE_NOTIFY_CHANGE_SIZE,
    FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_NOTIFY_CHANGE_SECURITY);
var
  cA: TJvChangeAction;
  Flags: Cardinal;
  I: Integer;
  S: string;
begin
  if (FActive <> Value) then
  begin
    FActive := Value;
    if csDesigning in ComponentState then
      Exit;   //active is now published

    if FActive then
    begin
      if FCollection.Count > MAXIMUM_WAIT_OBJECTS then
        raise EJVCLException.CreateResFmt(@RsEFmtMaxCountExceeded,[MAXIMUM_WAIT_OBJECTS]);
      FillChar(FNotifyArray, SizeOf(TJvNotifyArray), INVALID_HANDLE_VALUE);
      for I := 0 to FCollection.Count - 1 do
      begin
        Flags := 0;
        { convert TJvChangeActions to bitfields }
        for cA := Low(TJvChangeAction) to High(TJvChangeAction) do
          if cA in FCollection[I].Actions then
            Flags := Flags or (cActions[cA]);
        S := FCollection[I].Directory;
        if (Length(S) = 0) or not DirectoryExists(S) then
          raise EJVCLException.CreateResFmt(@RsEFmtInvalidPathAtIndex, [S, I]);
        FNotifyArray[I] := FindFirstChangeNotification(PChar(S),
          BOOL(FCollection[I].IncludeSubTrees), Flags);
        if FNotifyArray[I] = INVALID_HANDLE_VALUE then
          NotifyError(FCollection[I].Directory);
      end;
      if FThread <> nil then
      begin
        FThread.Terminate;
        if FreeOnTerminate then
          FThread := nil
        else
        begin
          FThread.WaitFor;
          FreeAndNil(FThread);
        end;
      end;
      FThread := TJvChangeThread.Create(FNotifyArray, FCollection.Count, FInterval, FFreeOnTerminate);
      FThread.OnChangeNotify := DoThreadChangeNotify;
      FThread.OnTerminate := DoThreadTerminate;
      FThread.Resume;
    end
    else
    if FThread <> nil then
    begin
      FThread.Terminate;
      if FreeOnTerminate then
        FThread := nil
      else
      begin
        FThread.WaitFor;
        FreeAndNil(FThread);
      end;
    end;

    {
      while FActive do
      begin
        I := WaitForMultipleObjects(FCollection.Count, @FNotifyArray, False, FInterval);
        if (I >= 0) and (I < FCollection.Count) then
        begin
          try
            Change(FCollection.Items[I]);
          finally
            Assert(FindNextChangeNotification(FNotifyArray[I]));
          end;
        end
        else
          Application.ProcessMessages;
      end;
    for I := 0 to FCollection.Count - 1 do // Iterate
      FindCloseChangeNotification(FNotifyArray[I]);
      }
  end;
end;

procedure TJvChangeNotify.Loaded;
begin
  inherited Loaded;
  if FActive then
  begin
    FActive := False;
    SetActive(True);
  end;
end;

//=== { TJvChangeThread } ====================================================

constructor TJvChangeThread.Create(NotifyArray: TJvNotifyArray; Count, Interval: Integer; AFreeOnTerminate:Boolean);
var
  I: Integer;
begin
  inherited Create(True);
  FCount := Count;
  FInterval := Interval;
  FillChar(FNotifyArray, SizeOf(TJvNotifyArray), INVALID_HANDLE_VALUE);
  for I := 0 to FCount - 1 do
    FNotifyArray[I] := NotifyArray[I];
  FreeOnTerminate := AFreeOnTerminate;
end;

procedure TJvChangeThread.Execute;
var
  I: Integer;
begin
  // (rom) secure thread against exceptions (Delphi 5 needs it)
  try
    while not Terminated do
    begin
      I := WaitForMultipleObjects(FCount, @FNotifyArray[0], False, FInterval);
      if (I >= 0) and (I < FCount) then
      begin
        try
          FIndex := I;
          Synchronize(SynchChange);
        finally
          // (rom) raising an exception in a thread is not a good idea
          // (rom) Assert removed
          //Assert(FindNextChangeNotification(FNotifyArray[I]));
          FindNextChangeNotification(FNotifyArray[I]);
        end;
      end;
    end;
    if Terminated then
      for I := 0 to FCount - 1 do
        if FNotifyArray[I] <> INVALID_HANDLE_VALUE then
        begin
          FindCloseChangeNotification(FNotifyArray[I]);
          FNotifyArray[I] := INVALID_HANDLE_VALUE;
        end;
  except
  end;
end;

procedure TJvChangeThread.SynchChange;
begin
  if Assigned(FNotify) then
    FNotify(Self, FIndex);
end;

{$IFDEF UNITVERSIONING}
initialization
  RegisterUnitVersion(HInstance, UnitVersioning);

finalization
  UnregisterUnitVersion(HInstance);
{$ENDIF UNITVERSIONING}

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -