首页  编辑  

IP地址控件

Tags: /超级猛料/VCL/Control.控件使用开发和第三方控件/自定义控件/   Date Created:

为 Delphi/C++ Builder 增添 IP 控件

西安交通大学

刘明华

在进行网络设置时,我们常常碰到需要填写 IP 地址的情况,为此 Windows 引入了一个专门用来接受 IP 地址输入的控件(如图所示)。 Windows IP 地址编辑控件( IP Address edit control )是随着微软的 Internet Explorer 4.0 的推出而引入 Windows 操作系统的( Windows 98 和 Windows 2000 中都已经包含了此控件)。但是令人遗憾的是在 Inprise 公司最新版本的 Delphi 5 和 C++ Builder 5 中, Borland 可视化控件库( Visual Component Library )中居然没有提供 IP 地址编辑控件。

为了让 Delphi 和 C++ Builder 开发人员更方便地使用 IP 控件,本文介绍如何将它包装成一个可以在 Delphi 和 C++ Builder 的 IDE 环境中使用的可视化 Delphi 控件。同时本文也为读者学习 Delphi 控件编写提供了一个比较好的示例;它涉及了 Delphi 控件编写的以下方面的知识:将 Windows 窗口类封装成 Delphi 控件,将 Windows 消息映射成事件属性,多个属性共享 read 和 write 方法,以及属性编辑器( Property Editor )的构造。

IP 控件的属性、方法及事件

本文将为 Delphi/C++ Builder 的 IP 控件实现下面的属性、方法和事件。它们的简单介绍如下:

IP 属性 : IP 控件中的 IP 地址值 (32 位整数 LongWord) 。为了获取 IP 控件的 IP 值,我们只需要读取此属性即可;通过对 IP 属性赋值,我们就能够改变 IP 控件的内容。

Field0..Field3 属性 : Field0 到 Field3 分别为 IP 控件的 4 个部分的值。这四个属性也是为了读取和改变 IP 控件的 IP 值而设置的。

Field0Range..Field3Range 属性 : Field0Range 到 Field3Range 限制 IP 控件各部分的取值的范围。

Blank 属性 :判断 IP 控件的 IP 串是否为空,此属性为只读属性。

About 属性 :在 Object Inspector 中点击它可以显示控件的版本信息,添加此属性是为了提供一个编写属性编辑器的简单例子。

       以下属性继承自 TWinControl 类: Font 、 TabOrder 、 TabStop 、 ParentShowHint 、 ShowHint 、 Hint 、及 Visible 。

TIPEdit 的事件属性有: OnFieldChange 、 OnChange 、 OnEnter 以及 OnExit 。

Clear 方法 :清空 IP 控件中的 IP 串。

SetFieldFocus 方法 :设置 IP 控件的输入焦点。

IP 控件的实现

// 文件名: IPEdit.PAS

{ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

//                 IP address edit control for Borland Delphi 5

//                Implemented by Simon Liu (simon_liu@263.net)

{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

unit IPEdit;

interface

uses Windows, Messages, SysUtils, Classes,

Forms, Controls, ComCtrls, CommCtrl, DsgnIntf;

type

 TFieldRange = record

   LowRange: Byte;

   HighRange: Byte;

 end;

 TFieldChangeEvent = procedure(Sender: TObject; OldField, Value: Byte) of Object;

 // 定义 TAboutProperty 属性编辑器

 TAboutProperty = class(TPropertyEditor)

 public

   procedure Edit; override;

   function GetAttributes: TPropertyAttributes; override;

   function GetValue: string; override;

 end;

 TIPEdit = class(TWinControl)

 private

   fAbout:TAboutProperty;

   FIP: LongWord;

   FFields:array[0..3] of Byte;

   FFieldRanges: array [0..3] of TFieldRange;

   FCreating: Boolean;

   FOnChange: TNotifyEvent;

   FOnEnter: TNotifyEvent;

   FOnExit: TNotifyEvent;

   FOnFieldChange: TFieldChangeEvent;

   procedure SetIP(Value: LongWord);

   function GetIP: LongWord;

   function  GetField(Index:Integer):Byte;

   procedure SetField(Index:Integer; B:Byte);

   function GetFieldRange(Field: Integer): TFieldRange;

   procedure SetFieldRange(Field:integer; Value: TFieldRange);

   procedure SetIPAddress;

   function GetBlank: Boolean;

   procedure WMNotifyFormat(var Message: TMessage); message WM_NOTIFYFORMAT;

   // 处理 IP 控件的通知消息 IPN_FIELDCHANGED

   procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;

   procedure CNCommand(var Message: TWMCommand); message CN_COMMAND;

   procedure WMSetFont(var Message: TWMSetFont); message WM_SETFONT;

 protected

   procedure CreateParams(var Params: TCreateParams); override;

   procedure CreateWnd; override;

   procedure DestroyWnd; override;

 public

   constructor Create(AOwner: TComponent); override;

   destructor Destroy; override;

   // 清除 IP 控件中的 IP 串

   procedure Clear;

  // 设置 IP 控件的输入焦点( field 的有效取值为 0..3 )

   procedure SetFieldFocus(Field:Byte);

 published

   // 判断 IP 控件的 IP 串是否为空

   property Blank: Boolean read GetBlank;

   //Field0 到 Field3 分别为 IP 控件的 4 个部分的值

   property Field0: Byte index 0 read GetField write SetField;

   property Field1: Byte index 1 read GetField write SetField;

   property Field2: Byte index 2 read GetField write SetField;

   property Field3: Byte index 3 read GetField write SetField;

  //Field0Range 到 Field3Range 限制 IP 控件各部分的取值的范围

   property Field0Range: TFieldRange index 0 read GetFieldRange write SetFieldRange;

   property Field1Range: TFieldRange index 1 read GetFieldRange write SetFieldRange;

   property Field2Range: TFieldRange index 2 read GetFieldRange write SetFieldRange;

   property Field3Range: TFieldRange index 3 read GetFieldRange write SetFieldRange;

   //IP 地址值 (32 位整数 LongWord)

   property IP: LongWord read GetIP write SetIP;

   //The About box

   property About:TAboutProperty read fAbout;

   // 事件属性

   property OnChange: TNotifyEvent read FOnChange write FOnChange;

   property OnEnter: TNotifyEvent read FOnEnter write FOnEnter;

   property OnExit: TNotifyEvent read FOnExit write FOnExit;

   property OnFieldChange: TFieldChangeEvent read FOnFieldChange write FOnFieldChange;

  // 以下属性继承自 TWinControl 控件

   property Enabled;

   property TabOrder;

   property TabStop;

   property ParentShowHint;

   property ShowHint;

   property Hint;

   property Visible;

 end;

procedure Register;

implementation

{~~~~~~~~~~~~~~~~~TAboutProperty~~~~~~~~~~~~~~~~~~~~~}

procedure TAboutProperty.Edit;

begin

Application.MessageBox(

 'TIPEdit for Delphi 5'#13

 +'(C) 2000 by Simon Liu'#13

 +'Email:simon_liu@263.net',

 'About TIPEdit',MB_ICONINFORMATION);

end;

function TAboutProperty.GetAttributes: TPropertyAttributes;

begin

 Result := [paDialog, paReadOnly];

end;

function TAboutProperty.GetValue: string;

begin

 Result := '(Simon)';

end;

{~~~~~~~~~~~~~~~~~~~~~~TIPEdit~~~~~~~~~~~~~~~~~~~~~~~~}

constructor TIPEdit.Create(AOwner: TComponent);

var

 i: integer;

begin

 // 初始化 ICC_INTERNET_CLASSES 类控件

 CheckCommonControl(ICC_INTERNET_CLASSES);

 inherited Create(AOwner);

 for i:= 0 to 3 do

 begin

   FFieldRanges[i].LowRange:= 0;

   FFieldRanges[i].HighRange:= 255;

   FFields[i]:=0;

 end;

 FIP:=0;

 Height:= 25;

 Width:= 152;

 TabSTop:= True;

end;

procedure TIPEdit.DestroyWnd;

begin

 inherited DestroyWnd

end;

destructor TIPEdit.Destroy;

begin

 inherited Destroy;

end;

procedure TIPEdit.CreateParams(var Params: TCreateParams);

begin

 inherited CreateParams(Params);

 CreateSubClass(Params, WC_IPADDRESS);

 with Params do

 begin

 end;

end;

procedure TIPEdit.CreateWnd;

begin

 FCreating := True;

 try

   inherited CreateWnd;

   SetIPAddress;

 finally

   FCreating := False;

 end;

end;

function TIPEdit.GetBlank: Boolean;

begin

 Result:= Boolean(SendMessage(Handle, IPM_ISBLANK, 0, 0));

end;

procedure TIPEdit.Clear;

begin

 SendMessage(Handle, IPM_CLEARADDRESS, 0, 0);

end;

procedure TIPEdit.SetFieldFocus(Field:Byte);

begin

 SendMessage(Handle, IPM_SETFOCUS, Field, 0);

end;

function TIPEdit.GetFieldRange(Field: Integer): TFieldRange;

begin

 Result:= FFieldRanges[Field];

end;

procedure TIPEdit.SetFieldRange(Field: Integer; Value: TFieldRange);

begin

 if Value.LowRange > Value.HighRange then exit;

 if (FFieldRanges[Field].LowRange <> Value.LowRange) or

   (FFieldRanges[Field].HighRange <> Value.HighRange) then

 begin

   FFieldRanges[Field]:= Value;

   SendMessage(Handle, IPM_SETRANGE, Field,

     MakeIPRange(Value.LowRange, Value.HighRange));

 end;

end;

function TIPEdit.GetField(Index: Integer): Byte;

begin

 if (Index>=0)and(Index<=3) then Result:=FFields[Index]

 else Result:=0;

end;

procedure TIPEdit.SetField(Index:Integer; B:Byte);

begin

 if (FFields[Index] <> B)then

 begin

   FFields[Index]:=B;

   SetIPAddress;

 end;

end;

procedure TIPEdit.SetIPAddress;

var

 i:LongWord;

begin

 i:=MAKEIPADDRESS(FFields[0], FFields[1], FFields[2], FFields[3]);

 SendMessage(Handle, IPM_SETADDRESS, 0, i);

 FIP:=i;

end;

procedure TIPEdit.SetIP(Value: LongWord);

begin

 if (FIP <> Value) then

 begin

   FFields[0]:= First_IPAddress(Value);

   FFields[1]:= Second_IPAddress(Value);

   FFields[2]:= Third_IPAddress(Value);

   FFields[3]:= Fourth_IPAddress(Value);

   SetIPAddress;

 end;

end;

function TIPEdit.GetIP: LongWord;

begin

 SendMessage(Handle, IPM_GETADDRESS, 0, Integer(@Result));

end;

procedure TIPEdit.WMSetFont(var Message: TWMSetFont);

begin

// 不可以调用父控件的此方法

// 否则,控件不能正常工作

end;

procedure TIPEdit.WMNotifyFormat(var Message: TMessage);

begin

 with Message do

   Result := DefWindowProc(Handle, Msg, WParam, LParam);

end;

procedure TIPEdit.CNNotify(var Message: TWMNotify);

var

 pNM: PNMIPAddress;

begin

 with (Message.NMHdr)^ do

 begin

   case Code of

     IPN_FIELDCHANGED:

           begin

         pNM:= PNMIPADDRESS(Message.NMHdr);

         if (pNM^.iField>=0)and(pNM^.iField<=3) then

           FFields[pNM^.iField]:=pNM^.iValue;

         if Assigned(FOnFieldChange) then

           FOnFieldChange(self, pNM^.iField, pNM^.iValue);

           end;

   end;

 end;

end;

procedure TIPEdit.CNCommand(var Message: TWMCommand);

begin

 case Message.NotifyCode of

   EN_CHANGE:

   begin

     if not FCreating then

       if Assigned(FOnChange) then FOnChange(self);

   end;

   EN_KILLFOCUS: if Assigned(FOnExit) then FOnExit(self);

   EN_SETFOCUS: if Assigned(FOnEnter) then FOnEnter(self);

 end;

end;

// 注册 TIPEdit 控件以及 TAboutProperty 属性编辑器

procedure Register;

begin

 RegisterComponents('Simon', [TIPEdit]);

 RegisterPropertyEditor(typeInfo(TAboutProperty),

   TIPEdit, 'ABOUT', TAboutProperty);

end;

end.

img_17048.bmp (164.0KB)