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

📄 idipaddrmon.pas

📁 photo.163.com 相册下载器 多线程下载
💻 PAS
字号:
{ $HDR$}
{**********************************************************************}
{ Unit archived using Team Coherence                                   }
{ Team Coherence is Copyright 2002 by Quality Software Components      }
{                                                                      }
{ For further information / comments, visit our WEB site at            }
{ http://www.TeamCoherence.com                                         }
{**********************************************************************}
{}
{ $Log:  14639: IdIPAddrMon.pas }
{
{   Rev 1.7    10/26/2004 10:20:04 PM  JPMugaas
{ Updated refs.
}
{
{   Rev 1.6    2004.02.03 5:45:14 PM  czhower
{ Name changes
}
{
{   Rev 1.5    1/31/2004 1:18:40 PM  JPMugaas
{ Illiminated Todo; item so it should work in DotNET.
}
{
{   Rev 1.4    1/21/2004 3:11:04 PM  JPMugaas
{ InitComponent
}
{
    Rev 1.3    10/19/2003 4:51:34 PM  DSiders
  Added localization comments.
}
{
{   Rev 1.2    2003.10.12 3:53:12 PM  czhower
{ compile todos
}
{
    Rev 1.1    3/5/2003 11:41:14 PM  BGooijen
  Added IdCoreGlobal to the uses, this file was needed for the call to
  Sleep(...)
}
{
    Rev 1.0    12/28/2002 3:04:52 PM  DSiders
  Initial revision.
}
unit IdIPAddrMon;

{

  TIdIPAddrMon

  Monitors adapters known to the IP protocol stack for changes in any
  of the IP addresses.  Similar to TIdIPWatch, but monitors all IP
  addresses/adapters.

  Does not keep a permanent IP address history list.  But does trigger
  a TIdIPAddrMonEvent event to signal the adapter number, old IP, and
  new IP for the change in status.

  OnStatusChanged is used to capture changed IP addresses, and/or
  to sync with GUI display controls.  If you do not assign a procedure
  for the event handler, this component essentially does nothing except
  eat small amounts of CPU time.

  The thread instance is created and freed when the value in Active is
  changed.


  TIdIPAddrMonEvent

  An procedure use to handle notifications from the component. Includes
  parameters that represent the adapter number, previous IP or '<unknown>',
  and the current IP or '<unknown>'.


  TIdIPAddrMonThread

  Timer thread for the IP address monitor component.  Based on
  TIdIPWatchThread.

  Sleeps in increments of .5 seconds until the Interval has elapsed, and
  fires the timer event.  Sleep is called in increments to allow checking
  for Terminated when a long Interval has been specified.


  Original Author:

  Don Siders, Integral Systems, Fri 27 Dec 2002

  Donated to the Internet Direct (Indy) Project for use under the
  terms of the Indy Dual License.

}

interface

uses
  Classes,
  IdComponent,
  IdThread,
  IdTStrings;

const
  IdIPAddrMonInterval = 500;

type

  TIdIPAddrMonEvent =
    procedure(ASender: TObject; AAdapter: Integer; AOldIP, ANewIP: string) of object;

  TIdIPAddrMonThread = class(TIdThread)
  protected
    FOwner: TObject;
    FInterval: Cardinal;
    FOnTimerEvent: TNotifyEvent;

    procedure Run; override;
    procedure DoTimerEvent;
  end;

  TIdIPAddrMon = class(TIdComponent)
  private
    FActive: Boolean;
    FBusy: Boolean;
    FInterval: Cardinal;
    FAdapterCount: Integer;
    FThread: TIdIPAddrMonThread;
    FIPAddresses: TIdStrings;
    FPreviousIPAddresses: TIdStrings;
    FOnStatusChanged: TIdIPAddrMonEvent;

    procedure SetActive(Value: Boolean);
    procedure SetAdapterCount(const Value: Integer);
    procedure SetBusy(const Value: Boolean);
    procedure SetInterval(Value: Cardinal);
    procedure GetAdapterAddresses;
    procedure DoStatusChanged;

  protected
    procedure InitComponent; override;
  public
    destructor Destroy; override;
    procedure CheckAdapters(Sender: TObject);
    procedure ForceCheck;

  published
    property Thread: TIdIPAddrMonThread read FThread;
    property Active: Boolean read FActive write SetActive;
    property Busy: Boolean read FBusy write SetBusy;
    property Interval: Cardinal read FInterval write SetInterval default IdIPAddrMonInterval;
    property AdapterCount: Integer read FAdapterCount write SetAdapterCount;
    property IPAddresses: TIdStrings read FIPAddresses;
    property OnStatusChanged: TIdIPAddrMonEvent read FOnStatusChanged write FOnStatusChanged;

  end;

implementation

uses
  IdGlobal,
  IdStack,
  SysUtils;

procedure TIdIPAddrMon.InitComponent;
begin
  inherited;

  FInterval := IdIPAddrMonInterval;
  FActive := False;
  FBusy := False;
  FAdapterCount := 0;

  FIPAddresses := TIdStringList.Create;
  FPreviousIPAddresses := TIdStringList.Create;

  // FThread created when component becomes Active
end;

destructor TIdIPAddrMon.Destroy;
begin
  Active := False;
  Busy := False;

  FIPAddresses.Free;
  FPreviousIPAddresses.Free;

  // FThread freed on Terminate

  inherited Destroy;
end;

procedure TIdIPAddrMon.CheckAdapters(Sender: TObject);
begin

  // previous check could still be running...
  if Busy then
  begin
    exit;
  end;

  try
    Busy := True;

    try
      GetAdapterAddresses;

      // something changed at runtime
      if (not (csDesigning in ComponentState)) and
        ((FPreviousIPAddresses.Count <> FIPAddresses.Count) or
          (FPreviousIPAddresses.Text <> FIPAddresses.Text)) then
      begin
        DoStatusChanged;
      end;

    except
      // eat any exception
    end;

  finally
    Busy := False;
  end;

end;

procedure TIdIPAddrMon.DoStatusChanged;
var
    iOldCount: Integer;
    iNewCount: Integer;
    iAdapter: Integer;
    sOldIP: string;
    sNewIP: string;
begin

  if (not Assigned(FOnStatusChanged)) then
  begin
    exit;
  end;

  // figure out the change... new, removed, or altered IP for adapter(s)
  iOldCount := FPreviousIPAddresses.Count;
  iNewCount := FIPAddresses.Count;

  // find the new adapter IP address
  if (iOldCount < iNewCount) then
  begin
    sOldIP := '<unknown>';  {do not localize}

    for iAdapter := 0 to iNewCount - 1 do
    begin
      sNewIP := FIPAddresses[iAdapter];

      if (FPreviousIPAddresses.IndexOf(sNewIP) = -1) then
      begin
        FOnStatusChanged(Self, iAdapter, sOldIP, sNewIP);
      end;
    end;
  end

  // find the missing adapter IP address
  else if (iOldCount > iNewCount) then
  begin
    sNewIP := '<unknown>';  {do not localize}

    for iAdapter := 0 to iOldCount - 1 do
    begin
      sOldIP := FPreviousIPAddresses[iAdapter];

      if (FIPAddresses.IndexOf(sOldIP) = -1) then
      begin
        FOnStatusChanged(Self, iAdapter, sOldIP, sNewIP);
      end;
    end;
  end

  // find the altered adapter IP address
  else
  begin
    for iAdapter := 0 to AdapterCount - 1 do
    begin
      sOldIP := FPreviousIPAddresses[iAdapter];
      sNewIP := FIPAddresses[iAdapter];

      if (sOldIP <> sNewIP) then
      begin
        FOnStatusChanged(Self, iAdapter, sOldIP, sNewIP);
      end;
    end;
  end;

end;

procedure TIdIPAddrMon.ForceCheck;
begin
  CheckAdapters(Nil);
end;

procedure TIdIPAddrMon.SetActive(Value: Boolean);
begin

  if Value <> FActive then
  begin
    FActive := Value;

    if (FActive) then
    begin
      // get initial addresses at start-up and allow display in IDE
      GetAdapterAddresses;
    end;

    if not (csDesigning in ComponentState) then
    begin
      if FActive then
      begin
        FThread := TIdIPAddrMonThread.Create(True);
        with FThread do
        begin
          FOwner := Self;
          FOnTimerEvent := CheckAdapters;
          FInterval := Self.Interval;

          Start;
        end;
      end

      else
      begin
        FThread.TerminateAndWaitFor;
        FreeAndNil(FThread);
      end;
    end;
  end;

end;

procedure TIdIPAddrMon.SetInterval(Value: Cardinal);
begin

  if Value <> FInterval then
  begin
    FInterval := Value;
  end;

  if Assigned(FThread) then
  begin
    FThread.FInterval := FInterval;
  end;

end;

procedure TIdIPAddrMonThread.Run;
var
  lInterval: Integer;
begin

  lInterval := FInterval;

  while (lInterval > 0) do
  begin
    // force a check for terminated every .5 sec
    if lInterval > 500 then
    begin
      Sleep(500);
      lInterval := lInterval - 500
    end

    else
    begin
      Sleep(lInterval);
      LInterval := 0;
    end;

    if Terminated then
    begin
      exit;
    end;
  end;

  // interval has elapsed... fire the thread timer event
  Synchronize(DoTimerEvent);

end;

procedure TIdIPAddrMonThread.DoTimerEvent;
begin
  if Assigned(FOnTimerEvent) then
    FOnTimerEvent(FOwner);
end;

procedure TIdIPAddrMon.SetAdapterCount(const Value: Integer);
begin
  FAdapterCount := Value;
end;

procedure TIdIPAddrMon.SetBusy(const Value: Boolean);
begin
  FBusy := Value;
end;

procedure TIdIPAddrMon.GetAdapterAddresses;
begin
  {
    Doesn't keep a permanent history list like TIdIPWatch...
    but does track previous IP addresses to detect changes.
  }
  FPreviousIPAddresses.Text := FIPAddresses.Text;
  FIPAddresses.Text := GStack.LocalAddresses.Text;
  AdapterCount := GStack.LocalAddresses.Count;
end;

end.

⌨️ 快捷键说明

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