自定义组件-IPEdit

时间:2022-12-29 20:15:17

输入IP用的.....支持windows风格显示

unit HSIPEdit;

//  ***************************************************************************
//
// IPEdit
//
// 版本: 1.2
// 作者: 刘志林
// 修改日期: 2017-04-29
// QQ: 17948876
// E-mail: lzl_17948876@hotmail.com
// 博客: http://www.cnblogs.com/lzl_17948876/
//
// !!! 若有修改,请通知作者,谢谢合作 !!!
//
// ---------------------------------------------------------------------------
//
// 修改历史:
// 1.1
// 增加对IPV6的支持
// 1.2
// 修改未获得焦点时, 鼠标点击焦点定位的问题
//
// *************************************************************************** interface uses
Messages, Windows, SysUtils, Classes, Controls, Forms,
Graphics, StdCtrls, ExtCtrls, Themes; const
{激活下一列, WParam: 列序号 LParam: 是否全选 0-不选 1-选}
WM_IPFIELD_ACTIVE = WM_USER + $; type
THSIPField = class(TCustomEdit)
private
{ Private declarations }
FMin, FMax: Word;
FIndex: Byte;
FIPV6: Boolean;
FIsSetValue: Boolean; function GetError: Boolean;
function GetValue: Word;
procedure SetMin(AValue: Word);
procedure SetMax(AValue: Word);
procedure SetValue(AValue: Word);
procedure SetIPV6(AValue: Boolean);
function GetCurrentPosition: Integer;
procedure SetCurrentPosition(Value: Integer); procedure WMKeyDown(var Message: TWMKey); message WM_KEYDOWN;
procedure CreateParams(var Params: TCreateParams); override;
procedure KeyPress(var Key: Char); override;
protected
{ Protected declarations }
procedure Change; override; procedure SetValueStr(AValue: string);
procedure ActiveField(ANext, ASel: Boolean); constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property IPV6: Boolean read FIPV6 write SetIPV6;
property CurrentPosition: integer read GetCurrentPosition write SetCurrentPosition;
property ReadOnly stored False;
property Index: Byte read FIndex;
published
{ Published declarations }
property Min: Word read FMin write SetMin default ;
property Max: Word read FMax write SetMax default ;
property Value: Word read GetValue write SetValue default ;
property Error: Boolean read GetError;
end; THSIPEdit = class(TCustomControl)
private
FUpdatting: Boolean;
FIPV6: Boolean;
{如果IPV4则使用后4位}
FFields: array[..] of THSIPField;
FFullRepaint: Boolean;
FOnChange: TNotifyEvent; procedure CreateParams(var Params: TCreateParams); override; function GetFieldCount: Byte;
function GetFieldValue(Index: Byte): Integer;
function GetMin(nIndex: Byte): Word;
procedure SetMin(nIndex: Byte; Value: Word);
function GetMax(nIndex: Byte): Word;
procedure SetMax(nIndex: Byte; Value: Word);
function GetIPString: string;
procedure SetIPString(Value: string);
function GetTabStop: Boolean;
procedure SetTabStop(AValue: Boolean);
procedure SetReadOnly(AValue: Boolean);
function GetReadOnly: Boolean;
function FocusIndex: Integer;
function GetFields(AIndex: Integer): THSIPField;
function GetCursor(): TCursor;
procedure SetCursor(AValue: TCursor);
function GetError: Boolean;
procedure SetIPV6(const Value: Boolean); procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
procedure WMSize(var Message: TWMSize); message WM_SIZE;
procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
procedure WMIPFIELDACTIVE(var Message: TMessage); message WM_IPFIELD_ACTIVE;
procedure DoChange(Sender: TObject);
protected
procedure ArrangeFields;
procedure Paint; override;
property FullRepaint: Boolean read FFullRepaint write FFullRepaint default True;
property Fields[index: Integer]: THSIPField read GetFields;
(*
function GetAddr: integer;
procedure SetAddr(value: integer);
*)
{暂时不开放设置}
property Min[index: Byte]: Word read GetMin write SetMin;
property Max[index: Byte]: Word read GetMax write SetMax; public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
(*
property Addr: integer read GetAddr write SetAddr;
*)
property FieldCount: Byte read GetFieldCount;
property FieldValue[Index: Byte]: Integer read GetFieldValue;
property Error: Boolean read GetError;
published
property Align;
property Anchors;
property IPString: string read GetIPString write SetIPString;
property BevelEdges;
property BevelInner;
property BevelKind default bkNone;
property BevelOuter;
property Color;
property Cursor: TCursor Read GetCursor write SetCursor;
property Ctl3D;
property Font;
property Enabled;
property ParentColor default False;
property ParentFont default True;
property ParentShowHint;
property PopupMenu;
property ReadOnly: Boolean read GetReadOnly write SetReadOnly default False;
property IPV6: Boolean read FIPV6 write SetIPV6 default False;
property ShowHint;
property TabOrder;
property TabStop: Boolean read GetTabStop write SetTabStop default True;
property Visible;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnEnter;
property OnExit;
end; implementation const
_DefWidthIPV4 = ;
_DefWidthIPV6 = ; { TIPFieldEdit } procedure THSIPField.SetMin(AValue: Word);
begin
if (not FIPV6) and (AValue > ) then
AValue := ;
FMin := AValue;
if FMax < FMin then
FMax := FMin;
end; procedure THSIPField.SetValueStr(AValue: string);
var
nValue, nCode: Integer;
begin
FIsSetValue := True;
try
if FIPV6 then
AValue := '$' + AValue; Val(AValue, nValue, nCode); if (nCode <> ) then
AValue := ''
else
begin
if (nValue < FMin) then
nValue := FMin
else if (nValue > FMax) then
nValue := FMax; if FIPV6 then
AValue := IntToHex(nValue, )
else
AValue := IntToStr(nValue);
end;
if AValue <> Text then
Text := AValue; if (Length(Text) = MaxLength) and (CurrentPosition = MaxLength) then
ActiveField(True, True);
finally
FIsSetValue := False;
end;
end; procedure THSIPField.SetMax(AValue: Word);
begin
if (not FIPV6) and (AValue > ) then
AValue := ;
FMax := AValue;
if FMin > FMax then
FMin := FMax;
end; procedure THSIPField.SetValue(AValue: Word);
begin
if FIPV6 then
SetValueStr(IntToHex(AValue, ))
else
SetValueStr(IntToStr(AValue));
end; procedure THSIPField.KeyPress(var Key: Char);
begin
if FIPV6 and (Key in [''..'', 'A'..'F']) then
begin
inherited;
end
else if (Key in [''..'']) then
begin
inherited;
end
else
begin
if (Key = '.') and (SelLength = ) and (Text <> '') then
ActiveField(True, True);
if Key <> # then
Key := #
else if CurrentPosition = then
ActiveField(False, False);
end;
end; procedure THSIPField.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.Style := Params.Style or (ES_CENTER);
end; procedure THSIPField.ActiveField(ANext, ASel: Boolean);
begin
if ANext then
SendMessage(Parent.Handle, WM_IPFIELD_ACTIVE, FIndex + , MakeLParam(Byte(ASel), ))
else
SendMessage(Parent.Handle, WM_IPFIELD_ACTIVE, FIndex - , MakeLParam(Byte(ASel), ));
end; procedure THSIPField.Change;
begin
if not FIsSetValue then
SetValueStr(Text);
inherited Change;
end; constructor THSIPField.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Text := '';
FMin := ;
FMax := ;
FIPV6 := False;
FIsSetValue := False;
MaxLength := ;
ParentFont := True;
ParentColor := True;
BorderStyle := bsNone;
end; destructor THSIPField.Destroy;
begin
inherited Destroy;
end; function THSIPField.GetCurrentPosition: Integer;
{Get character position of cursor within line}
begin
Result := SelStart - SendMessage(Handle, EM_LINEINDEX,
(SendMessage(Handle, EM_LINEFROMCHAR, SelStart, )), );
end; function THSIPField.GetError: Boolean;
var
nV: Integer;
begin
if FIPV6 then
Result := not TryStrToInt('$' + Text, nV)
else
Result := not TryStrToInt(Text, nV);
end; function THSIPField.GetValue: Word;
begin
if FIPV6 then
Result := StrToIntDef('$' + Text, )
else
Result := StrToIntDef(Text, );
end; procedure THSIPField.SetCurrentPosition(Value: Integer);
var
nPos: Integer;
begin
{Value must be within range}
nPos := Value;
if nPos < then
nPos := ;
if nPos > Length(Text) then
nPos := Length(Text);
{Put cursor in selected position}
SelStart := SendMessage(Handle, EM_LINEINDEX, , ) + nPos;
end; procedure THSIPField.SetIPV6(AValue: Boolean);
var
nV: string;
begin
if FIPV6 <> AValue then
begin
FIPV6 := AValue;
if FIPV6 then
begin
MaxLength := ;
FMax := $FFFF;
nV := IntToHex(StrToIntDef(Text, ), );
end
else
begin
MaxLength := ;
FMax := ;
nV := IntToStr(StrToIntDef('$' + Text, ));
end;
SetMax(FMax);
SetMin(FMin);
SetValueStr(nV);
end;
Visible := False;//FIPV6 or (FIndex > 3);
end; procedure THSIPField.WMKeyDown(var Message: TWMKey);
begin
with Message do
if (CharCode = VK_RIGHT) and (CurrentPosition >= Length(Text)) then
begin
SelLength := ;
ActiveField(True, False);
Result := ;
end
else if (CharCode = VK_LEFT) and (CurrentPosition = ) then
begin
SelLength := ;
ActiveField(False, False);
Result := ;
end
else
inherited;
end; { TIPEdit } constructor THSIPEdit.Create(AOwner: TComponent);
var
i: integer;
begin
inherited Create(AOwner);
ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents,
csSetCaption, csOpaque, csDoubleClicks, csReplicatable];
if NewStyleControls then
ControlStyle := ControlStyle else
ControlStyle := ControlStyle + [csFramed];
ParentFont := True;
FUpdatting := True;
FIPV6 := False;
for i := to do
begin
FFields[i] := THSIPField.Create(Self);
with FFields[i] do
begin
FIndex := i;
Parent := Self;
FIPV6 := Self.FIPV6;
OnChange := DoChange;
end;
end;
// Cursor := crIBeam;
Width := ;
Height := ;
BevelKind := bkFlat;
inherited TabStop := False;
ParentColor := False;
ArrangeFields;
FUpdatting := False;
end; destructor THSIPEdit.Destroy;
var
i: integer;
begin
for i := to do
FFields[i].Free;
inherited;
end; procedure THSIPEdit.DoChange(Sender: TObject);
begin
if Assigned(FOnChange) then
FOnChange(Self);
end; procedure THSIPEdit.CreateParams(var Params: TCreateParams);
const
ReadOnlys: array[Boolean] of DWORD = (, ES_READONLY);
begin
inherited CreateParams(Params);
with Params do
begin
Style := Style or ReadOnlys[ReadOnly];
WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
end;
end; procedure THSIPEdit.CMColorChanged(var Message: TMessage);
begin //
inherited;
Invalidate;
end; procedure THSIPEdit.CMFontChanged(var Message: TMessage);
begin //
inherited;
if not FUpdatting then
ArrangeFields;
Invalidate;
end; procedure THSIPEdit.CMCtl3DChanged(var Message: TMessage);
begin
inherited;
end; procedure THSIPEdit.Paint;
var
nRect: TRect;
nTop, i: Integer;
nFSize: TSize;
begin
// inherited;
nRect := GetClientRect; Canvas.Brush.Color := Color;
Canvas.FillRect(nRect); nFSize := Canvas.TextExtent('a');
nTop := nRect.Top + (nRect.Bottom - nRect.Top - nFSize.cy) div ;
if FIPV6 then
begin
for i := to do
Canvas.TextOut(FFields[i].Left - nFSize.cx - , nTop, ':');
end
else
begin
for i := to do
Canvas.TextOut(FFields[i].Left - nFSize.cx - , nTop, '.');
end;
end; function THSIPEdit.GetCursor(): TCursor;
begin
Result := inherited Cursor;
end; function THSIPEdit.GetError: Boolean;
var
i, m: Integer;
begin
Result := False;
if FIPV6 then
m :=
else
m := ; for i := m to do
if FFields[i].Error then
begin
Result := True;
Break;
end;
end; procedure THSIPEdit.SetCursor(AValue: TCursor);
var
i: integer;
begin
inherited Cursor := AValue;
for i := to do
FFields[i].Cursor := AValue;
end; procedure THSIPEdit.ArrangeFields;
var
i: integer;
nW, nH, nL, nT, nB: Integer;
nFSize: TSize;
nRC: TRect;
begin
if not Assigned(Parent) then
Exit;
nRC := ClientRect;
nFSize := Canvas.TextExtent('a');
nL := nRC.Left + ;
nH := nFSize.cy + ;
nT := nRc.Top + (nRC.Bottom - nRC.Top - nH) div + ; nB := nFSize.cx + ;
if FIPV6 then
begin
nW := (ClientWidth - - nB * ) div ;
for i := to do
begin
with FFields[i] do
begin
Enabled := True;
Visible := True;
SetBounds(nL, nT, nW, nH);
end;
Inc(nL, nW + nB);
end;
end
else
begin
nW := (ClientWidth - - nB * ) div ;
for i := to do
begin
with FFields[i] do
begin
Visible := False;
Enabled := False;
end;
end;
for i := to do
begin
FFields[i].SetBounds(nL, nT, nW, nH);
Inc(nL, nW + nB);
end;
end;
end; function THSIPEdit.GetMin(nIndex: Byte): Word;
begin
Result := FFields[nIndex].Min;
end; procedure THSIPEdit.SetMin(nIndex: Byte; Value: Word);
begin
FFields[nIndex].Min := Value;
end; function THSIPEdit.GetMax(nIndex: Byte): Word;
begin
Result := FFields[nIndex].Max;
end; procedure THSIPEdit.SetMax(nIndex: Byte; Value: Word);
begin
FFields[nIndex].Max := Value;
end; function THSIPEdit.GetIPString: string;
begin
if GetError then
Result := ''
else if FIPV6 then
Result := Format('%.4x:%.4x:%.4x:%.4x:%.4x:%.4x:%.4x:%.4x',
[FFields[].Value, FFields[].Value, FFields[].Value, FFields[].Value,
FFields[].Value, FFields[].Value, FFields[].Value, FFields[].Value])
else
Result := Format('%d.%d.%d.%d',
[FFields[].Value, FFields[].Value, FFields[].Value, FFields[].Value]);
end; procedure THSIPEdit.SetIPString(Value: string);
var
i, nF: integer;
begin
if FIPV6 then
nF :=
else
nF := ; with TStringList.Create do
try
if FIPV6 then
Delimiter := ':'
else
Delimiter := '.'; DelimitedText := Value;
{暂不支持IPV6缩写模式 如: 0::FF:0}
if Count <> ( - nF) then
for i := nF to do
FFields[i].SetValueStr('')
else
for i := nF to do
FFields[i].SetValueStr(Strings[i - nF]);
finally
Free;
end;
end; procedure THSIPEdit.SetIPV6(const Value: Boolean);
var
i: Integer;
begin
if FIPV6 <> Value then
begin
FUpdatting := True;
FIPV6 := Value;
for i := to do
FFields[i].IPV6 := FIPV6;
if FIPV6 then
begin
if Width = _DefWidthIPV4 then
Width := _DefWidthIPV6;
end
else
begin
if Width = _DefWidthIPV6 then
Width := _DefWidthIPV4;
end;
FUpdatting := False;
ArrangeFields;
Invalidate;
end;
end; (*
function THSIPEdit.GetAddr: integer;
type
DWORDSTRUCT = Record
case integer of
0: (b: array [0..3] of Byte);
1: (w: array [0..1] of word);
2: (d: Integer);
end;
var
v: DWORDSTRUCT;
i: integer;
begin
if Error then
Result := 0
else
begin
for i := 0 to 3 do
v.b[i] := FFields[i].Value;
Result := v.d;
end;
end; procedure THSIPEdit.SetAddr(value: integer);
type
DWORDSTRUCT = Record
case integer of
0: (b: array [0..3] of Byte);
1: (w: array [0..1] of word);
2: (d: integer);
end;
var
v: DWORDSTRUCT;
i: integer;
begin
v.d := value;
for i := 0 to 3 do
begin
FFields[i].Value := v.b[i];
end;
end;
*) function THSIPEdit.FocusIndex: Integer;
var
i: Integer;
begin
Result := -;
for i := to do
if FFields[i].Focused then
Result := i;
end; procedure THSIPEdit.WMSize(var Message: TWMSize);
begin
inherited;
if not FUpdatting then
ArrangeFields;
Invalidate;
end; procedure THSIPEdit.WMIPFIELDACTIVE(var Message: TMessage);
var
nF: integer;
nSel: Boolean;
begin
if FIPV6 then
nF :=
else
nF := ;
with Message do
begin
if (WParam < nF) or (WParam > ) then
Exit; nSel := Boolean(Byte(LParamLo));
if nSel then
FFields[WParam].SelectAll
else if LParamHi = then
FFields[WParam].CurrentPosition :=
else
FFields[WParam].CurrentPosition := Length(FFields[WParam].Text);
FFields[WParam].SetFocus;
end;
end; function THSIPEdit.GetFieldCount: Byte;
begin
if FIPV6 then
Result :=
else
Result := ;
end; function THSIPEdit.GetFields(AIndex: Integer): THSIPField;
begin
Result := FFields[AIndex];
end; function THSIPEdit.GetFieldValue(Index: Byte): Integer;
begin
Result := ;
if FIPV6 then
begin
if Index > then
Exit;
if FFields[Index].Error then
Exit;
Result := FFields[Index].Value;
end
else
begin
if Index > then
Exit;
if FFields[Index + ].Error then
Exit;
Result := FFields[Index + ].Value;
end;
end; function THSIPEdit.GetTabStop: Boolean;
begin
Result := FFields[].TabStop;
end; procedure THSIPEdit.SetTabStop(AValue: Boolean);
var
i: integer;
begin
if AValue <> TabStop then
begin
for i := to do
FFields[i].TabStop := AValue;
end;
end; procedure THSIPEdit.SetReadOnly(AValue: Boolean);
var
i: integer;
begin
if ReadOnly <> AValue then
for i := to do
FFields[i].ReadOnly := AValue;
end; function THSIPEdit.GetReadOnly: Boolean;
begin
Result := FFields[].ReadOnly;
end; end.

自定义组件-IPEdit的更多相关文章

  1. Android开发之自定义组件和接口回调

    说到自定义控件不得不提的就是接口回调,在Android开发中接口回调用的还是蛮多的.在这篇博客开始的时候呢,我想聊一下iOS的自定义控件.在iOS中自定义控件的思路是继承自UIView, 在UIVie ...

  2. Android自定义组件

    [参考的原文地址] http://blog.csdn.net/l1028386804/article/details/47101387效果图: 实现方式: 一:自定义一个含有EditText和Butt ...

  3. 自己写的几个android自定义组件

    http://www.see-source.com/androidwidget/list.html 多多指点,尤其是自定义组件的适配问题,希望能有更好的方法

  4. PhoneGap&colon; Android 自定义组件

    Hello Core Demo Plugin Development(组件部署): http://docs.phonegap.com/en/2.0.0/guide_plugin-development ...

  5. android开发之自定义组件

    android开发之自定义组件 一:自定义组件: 我认为,自定义组件就是android给我们提供的的一个空白的可以编辑的图片,它帮助我们实现的我们想要的界面,也就是通过自定义组件我们可以把我们要登入的 ...

  6. HTML5 UI框架Kendo UI Web教程:创建自定义组件(三)

    Kendo UI Web包 含数百个创建HTML5 web app的必备元素,包括UI组件.数据源.验证.一个MVVM框架.主题.模板等.在前面的2篇文章<HTML5 Web app开发工具Ke ...

  7. HTML5 UI框架Kendo UI Web中如何创建自定义组件(二)

    在前面的文章<HTML5 UI框架Kendo UI Web自定义组件(一)>中,对在Kendo UI Web中如何创建自定义组件作出了一些基础讲解,下面将继续前面的内容. 使用一个数据源 ...

  8. HTML5 UI框架Kendo UI Web自定义组件(一)

    Kendo UI Web包含数百个创建HTML5 web app的必备元素,包括UI组件.数据源.验证.一个MVVM框架.主题.模板等.在Kendo UI Web中如何创建自定义组件呢,在下面的文章中 ...

  9. 自定义组件之MoreListView

    前言 本文针对自定义组件进行一些分析.还是那句老话“授之于鱼不如授之以渔”.今天要讲的是一个自定义的可以分页的ListView. 网上都讲了些ListView分页的方法,那么为什么我在这里还需要自己写 ...

随机推荐

  1. 在Function对象上扩展method方法

    ;(function() { /** * 在Function对象上扩展method方法 * @param {String} name 扩展的方法名称 * @param {Function} callb ...

  2. &lpar;转&rpar;CentOS搭建Nagios监控

    A.Nagios服务端1.安装软件包 yum install -y httpd 2.下载nagios wget http://syslab.comsenz.com/downloads/linux/na ...

  3. 符号三角形(hdu 2510 搜索&plus;打表)

    符号三角形 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  4. 腾讯云部署Flask应用

    由于新浪云现在不免费了.而且云豆也用完了.所以去腾讯云申请了个学生云主机,一元一个月. 不过部署开发环境还是有点麻烦的,搞了好几天,终于部署成功了! 下面说部署过程: 我云主机用的是 Ubuntu 1 ...

  5. Response&period;Redirect&lpar;&rpar;和Response&period;RedirectPermanent&lpar;&rpar;区别

    备注:这里我用到了Response.RedirectPermanent()用于做301跳转, 如:我希望访问网站的url访问地址为:http://m.shop/abc.html ,用户输入的访问地址: ...

  6. &lbrack;Python&rsqb;&lbrack;小知识&rsqb;&lbrack;NO&period;3&rsqb; Python 使用系统默认浏览器打开指定URL的网址

    1.前言 一般用到的地方: GUI交互界面下,单击某个按钮实现打开指定网址. 某帮助菜单项目,需要跳转网页显示时. O.O 某XX程序,需要植入网页弹窗广告时... 2.方法 调用 webbrowse ...

  7. react-hot-loader 3&period;0于1&period;3的区别

    现在react-hot-loader 3.0版本应该还是beta版本,不过没关系,还是可以正常使用,我在项目中用的是react-hot-loader 3.0.0-beta.7 版本,并没用发现任何问题 ...

  8. J2SE 8的流库 --- 生成流

    本文介绍了如何产生J2SE 8的流, 包括基本类型的流IntStream, LongStream, DoubleStream . 展现流的方法 public static <T> void ...

  9. 关于RF对于不在屏幕内的页面元素的处理办法

    1.碰到的问题: 最近在公司用Robot framework+Selenium2Library做项目,碰到部分页面比较长,无法完全显示在屏幕内,需要上下滚动滚动条才能看到下半部分的页面元素.于是呼,问 ...

  10. &quot&semi;流量监管&quot&semi;和&quot&semi;流量整形&quot&semi;的区别

    "流量监管" (Traffic Policing) 就是对流量进行控制,通过监督进入交换机端口的流量速率,对超出部分的流量进行"惩罚" (采用监管方式时是直接丢 ...