注册 登录
编程论坛 VFP论坛

实用的一个文本框类,只能输入ip地址

sam_jiang 发布于 4 天前 00:50, 227 次点击
如题。

10/6更新代码如下:
程序代码:

DEFINE CLASS iptextbox as TextBox
    Height = 20
    InputMask = "###.###.###.###"
    Width = 114
    Name = "iptextbox"
   
    PROCEDURE init
        this.SelStart=0
        this.SelLength=3
    ENDPROC
   
    PROCEDURE keypress
    LPARAMETERS nKeyCode, nShiftAltCtrl

    DO CASE
        CASE nkeycode=32 OR nkeycode=9 OR nkeycode=46 OR nkeycode=13 &&space,tab,".",enter
            IF this.selstart>AT(".",this.value,3)
                IF nkeycode=32 OR nkeycode=46 OR nkeycode=13
                    NODEFAULT
                    KEYBOARD '{TAB}'
                ENDIF     
            ELSE
                NODEFAULT
                ctext=SUBSTR(this.Value,1,this.selstart)
                ndot=OCCURS(".",ctext) &&有几个“.”
                IF !(this.SelStart=AT(".",this.value,ndot) AND nkeycode=46)
                    ndot=IIF(ndot=3,3,ndot+1)
                    ndotpos=AT(".",this.value,ndot)
                    this.SelStart=ndotpos
                    this.SelLength=3
                ENDIF     
            ENDIF
   
        CASE BETWEEN(nkeycode,48,57) &&0-9
            NODEFAULT
            DODEFAULT()
*!*            上面2句必不可少,否则this.selstart的值不正确,这是通过下面这句代码发现的。
*!*            SET MESSAGE TO TRANSFORM(this.SelStart)) &&用来观察this.selstart的表现
            IF INLIST(this.SelStart,AT(".",this.Value,1),AT(".",this.Value,2),AT(".",this.Value,3))
                this.SelLength=3
            ENDIF
    ENDCASE            
    ENDPROC
   
    PROCEDURE valid
    n=ALINES(atemp,this.Value,5,".")
    IF n#4
        SET MESSAGE TO "每个地址段的值不能为空"
        RELEASE atemp
        RETURN .f.
    ELSE
        FOR i =1 TO ALEN(atemp)
            IF !BETWEEN(EVALUATE(atemp(i)),0,255)
                SET MESSAGE TO "无效的ip地址端值"+atemp(i)
                npos=AT(atemp(i),this.Value,1)-1
                this.SelStart=npos
                this.SelLength=3
                RELEASE atemp
                RETURN .f.
            ENDIF     
        ENDFOR   
    ENDIF
    endproc         
ENDDEFINE



[此贴子已经被作者于2025-10-6 21:41编辑过]

12 回复
#2
schtg4 天前 05:39
#3
sam_jiang4 天前 07:15
改天再发表一个电话号码类,只能输入电话号码,感觉挺实用的
#4
laowan0014 天前 07:15
#5
sam_jiang4 天前 21:25
10/6 更新代码,valid的判断更加完美,指出哪个值无效;
解决了每个地址端输入3个数字后的块选择问题,定位到错的地址段。

更新后的代码放到一楼了。。。
#6
吹水佬3 天前 23:19
windows也有个IP地址控件
简单示例
只有本站会员才能查看附件,请 登录

程序代码:

DECLARE long InitCommonControlsEx IN comctl32 string@
DECLARE long CreateWindowExA IN user32 long,string,string,long,long,long,long,long,long,long,long,long

of=CREATEOBJECT("form1")
of.show(1)
CLEAR ALL
RETURN

DEFINE CLASS form1 as Form
    PROCEDURE load
        icex = BINTOC(8,"4rs")+BINTOC(0x0800,"4rs")
        InitCommonControlsEx(@icex)
        CreateWindowExA(0,"SysIPAddress32","",0x50000000,10,10,150,22,this.hWnd,0,0,0)
    ENDPROC
ENDDEFINE
#7
schtg前天 06:28
#8
sam_jiang前天 07:09
这么简洁?!
居然还有这个控件?可以可视化调用吗?

在keypress中读取或设置selstart属性容易出现不可知的错误,所以代码量比较大且复杂,DS建议不要放在keypress里,那时selstart还没设置,建议放在InteractiveChange方法中,改天试试

[此贴子已经被作者于2025-10-8 07:28编辑过]

#9
吹水佬前天 07:30
以下是引用sam_jiang在2025-10-8 07:09:57的发言:

这么简洁?!
居然还有这个控件?可以可视化调用吗?

这个是windows的标准控件,实际应用中还有一些细节问题要处理,如编辑焦点和插入光标的处理。
MS参考文档:https://learn.

#10
吹水佬前天 08:03
简单的话用vfp的textbox写个IP解析就可以,如:
程序代码:

of=CREATEOBJECT("form1")
of.show(1)

DEFINE CLASS form1 as Form
    ADD OBJECT text1 as text_ip WITH left=10,top=10,width=100,height=20
ENDDEFINE

DEFINE CLASS text_ip as TextBox
    InputMask = "999.999.999.999"
    PROCEDURE valid
        ALINES(arr,this.Value,".")
        IF BETWEEN(VAL(arr[1]),0,255) AND ;
           BETWEEN(VAL(arr[2]),0,255) AND ;
           BETWEEN(VAL(arr[3]),0,255) AND ;
           BETWEEN(VAL(arr[4]),0,255)
           RETURN .t.
        ENDIF
        ERROR "IP地址输入无效"
        RETURN .f.
    ENDPROC
ENDDEFINE


#11
吹水佬前天 09:00
也可以模拟 Internet 协议的IP格式由四个三位数字段组成,每个字段单独处理。
实际应用中通常是用 in_addr 结构表示IP地址。
in_addr结构简单可以这样理解:
struct in_addr {
    u_char s_b1;
    u_char s_b2;
    u_char s_b3;
    u_char s_b4;
};

只有本站会员才能查看附件,请 登录

程序代码:

of=CREATEOBJECT("form1")
of.show(1)

DEFINE CLASS form1 as Form
    ADD OBJECT label1 as label WITH left=10,top=10,width=135,height=16,backcolor=0x00FFFFFF,;
        BorderStyle=1,caption="     .     .     .     "
    ADD OBJECT ip1 as text_ip WITH left=11,top=11,width=30,height=14
    ADD OBJECT ip2 as text_ip WITH left=42,top=11,width=30,height=14
    ADD OBJECT ip3 as text_ip WITH left=78,top=11,width=30,height=14
    ADD OBJECT ip4 as text_ip WITH left=114,top=11,width=30,height=14
ENDDEFINE

DEFINE CLASS text_ip as TextBox
    Alignment = 2
    BorderStyle = 0
    Margin = 0
    Format = "Z"
    InputMask = "999"
    value = 0
    PROCEDURE valid
        RETURN BETWEEN(this.Value,0,255)
    ENDPROC
ENDDEFINE

#12
foxfans前天 14:15
可以进一步完成兼容ipv4与6,下面是验证地址有效性(只判断)
CLEAR
DECLARE INTEGER inet_pton IN ws2_32.dll INTEGER af, STRING src, STRING @dst

cIPv4Addr = SPACE(4)
cInput = "192.168.1.1"
nResult = inet_pton(2, cInput, @cIPv4Addr)
IF nResult = 1 THEN
  ? "IPv4地址有效"
ELSE
  ? "IPv4地址无效"
ENDIF

cIPv6Addr = SPACE(16)
cInput = "2001:1db8:35a3:ff00:0130:8a2e:0370:7334"
nResult = inet_pton(23, cInput, @cIPv6Addr)
IF nResult = 1 THEN
  ? "IPv6地址有效"
ELSE
  ? "IPv6地址无效"
ENDIF
*!*    CLEAR DLLS "inet_pton"
#13
sam_jiang前天 17:37
回复 11楼 吹水佬
ds也是建议用container+textbox+label来解决

1