首页  编辑  

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)