📄 idipaddrmon.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 + -