注册 登录
编程论坛 VFP论坛

如何获得edit框的行数问题

sam_jiang 发布于 3 天前 15:52, 306 次点击
前一段时间有人提问如何获得编辑框里文字的行数,今天就试着写了一段代码,好像还能正确运行,特分享给大家。

运行效果图:
只有本站会员才能查看附件,请 登录

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


10/5 晚更新代码,符合微软雅黑20号字体。
源代码:
程序代码:

**************************************************
*-- Form:         form1 (d:\documents\visual foxpro 项目\edittest.scx)
*-- 父类:  form
*-- 基类:    form
*-- 时间戳:   11/05/25 09:38:11 PM
*
DEFINE CLASS form1 AS form


    Top = 0
    Left = 0
    Height = 559
    Width = 712
    DoCreate = .T.
    Caption = "Form1"
    Name = "Form1"


    ADD OBJECT edit1 AS editbox WITH ;
        Height = 552, ;
        Left = 0, ;
        Top = 0, ;
        Width = 421, ;
        Name = "Edit1"


    ADD OBJECT text1 AS textbox WITH ;
        Height = 20, ;
        Left = 509, ;
        Top = 12, ;
        Width = 100, ;
        Name = "Text1"


    ADD OBJECT text2 AS textbox WITH ;
        Height = 20, ;
        Left = 509, ;
        Top = 48, ;
        Width = 100, ;
        Name = "Text2"


    ADD OBJECT command1 AS commandbutton WITH ;
        AutoSize = .T., ;
        Top = 96, ;
        Left = 552, ;
        Height = 25, ;
        Width = 84, ;
        Caption = "计算字数与行", ;
        Name = "Command1"


    ADD OBJECT label1 AS label WITH ;
        AutoSize = .T., ;
        Caption = "每行字数:", ;
        Height = 16, ;
        Left = 432, ;
        Top = 16, ;
        Width = 62, ;
        Name = "Label1"


    ADD OBJECT label2 AS label WITH ;
        Caption = "行数:", ;
        Height = 16, ;
        Left = 434, ;
        Top = 50, ;
        Width = 38, ;
        Name = "Label2"


    ADD OBJECT command2 AS commandbutton WITH ;
        AutoSize = .T., ;
        Top = 144, ;
        Left = 480, ;
        Height = 25, ;
        Width = 156, ;
        Caption = "生成一串随机字符再次测试", ;
        Name = "Command2"


    PROCEDURE Init
        this.edit1.Value="SHA-1(Secure Hash Algorithm 1)是一种广泛使用的密码散列函数"+;
                        ",由美国国家安全局(NSA)设计,并由美国国家标准与技术研究院(NIST)"+;
                        "发布为联邦信息处理标准(FIPS PUB 180-1)。它能够将任意长度的"+;
                        "数据(消息)映射为固定长度(160位/20字节)的哈希值,通常用于数据"+;
                        "完整性校验、数字签名和密码存储等领域。"
    ENDPROC


    PROCEDURE command1.Click
        nhead=4 && 首字符距编辑框的距离
        *ntail=6 && fontname="宋体",fontsize=9的情况下 尾字符距滚动条的距离
        ntail=2 && fontname="雅黑",fontsize=20的情况下 尾字符距滚动条的距离
        nscollbar=21 &&滚动条的宽度
        *!*上面3个数据可能根据编辑框的不同字体会有不同结果
        *!*我的编辑框是宋体,9号字体,普通字体

        *!* 设置不同的字体和大小看看
        thisform.edit1.FontName=("微软雅黑")
        thisform.edit1.FontSize=20
        *!*
        nwidth=0
        i=0
        cchar=""
        cstr=""
        nevenwidth=FONTMETRIC(6,thisform.edit1.FontName,thisform.edit1.FontSize,"N")
        ctemp=thisform.edit1.Value
        PUBLIC lines
        DIMENSION lines[1]
        nindex=0
        DO WHILE .t.
            i=i+1
            IF i>LEN(ctemp)
                nindex=nindex+1
                DIMENSION lines[nindex]
                lines[nindex]=ctemp
                EXIT
            ENDIF
            cchar=SUBSTR(ctemp,i,1)
            IF ASC(cchar)>128
                i=i+1
            ENDIF
            cstr=SUBSTR(ctemp,1,i)
            nstrwidth=TXTWIDTH(cstr,thisform.edit1.FontName,thisform.edit1.FontSize,"N")
            nwidth=nhead+ntail+nscollbar+nstrwidth*nevenwidth
            IF nwidth>thisform.edit1.Width
        *!*            i=i-1
                IF ASC(cchar)>128
                    i=i-2 &&判断该行最后一个字符为汉字
                ELSE
                    i=i-1 &&英文字母
                ENDIF
                nindex=nindex+1
                DIMENSION lines[nindex]
                lines[nindex]=SUBSTR(ctemp,1,i)
                ctemp=STRTRAN(ctemp,lines[nindex],"")
                IF EMPTY(ctemp)
                    EXIT
                ELSE
                    i=0
                    LOOP
                ENDIF         
            ELSE
                LOOP
            ENDIF
        ENDDO
        thisform.text1.Value=LEN(lines[1])
        thisform.text2.Value=ALEN(lines)
    ENDPROC


    PROCEDURE command2.Click
        tnlength=256
        Rand(-1)
        lctext = ''
        i = 0
        Do While i < tnlength
            kb = 48 + Rand() * 80
            If kb <= 57 And kb >= 48 Or kb <= 122 And kb >= 97 Or kb <= 90 And kb >= 65
                i = i + 1
                lctext = lctext + Chr(kb)
            Endif
        Enddo

        thisform.edit1.value=lctext
    ENDPROC


ENDDEFINE
*
*-- EndDefine: form1
**************************************************



[此贴子已经被作者于2025-11-5 21:51编辑过]

14 回复
#2
sam_jiang3 天前 15:55
没有考虑到编辑框里可能存在换行符的情况,但是处理方式相同,可以以此类推。
#3
csyx3 天前 18:53
假如这么简单,就不会有人提这问题了。
改成这样试试
...
    ADD OBJECT edit1 AS editbox WITH ;
        Height = 409, ;
        Left = 0, ;
        Top = 0, ;
        Width = 421, ;
        FontName = '微软雅黑', ;
        FontSize = 16, ;
        Name = "Edit1"
...
如果把 FontSize 改成 20,自动换行的位置更能叫人抓狂

[此贴子已经被作者于2025-11-5 19:17编辑过]

#4
sam_jiang3 天前 19:49
回复 2楼 sam_jiang
不同的字体及size,会有不同的结果,雅黑就是个另类,大写小写的字符宽度都不一样的
#5
csyx3 天前 19:56
不是雅黑另类,字体本就分两类,一种等宽字体,一种比例字体;常见字体中绝大部分都是比例字体
等宽字体除了用于编辑源代码,极少用到;其他像广告、印刷、办公 等等等等都会使用比例字体

#6
sam_jiang3 天前 21:42
根据@csyx的反馈,更新command1的click代码如下:
只有本站会员才能查看附件,请 登录

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

程序代码:

nhead=4 && 首字符距编辑框的距离
*ntail=6 && fontname="宋体",fontsize=9的情况下 尾字符距滚动条的距离
ntail=2 && fontname="雅黑",fontsize=20的情况下 尾字符距滚动条的距离
nscollbar=21 &&滚动条的宽度
*!*上面3个数据可能根据编辑框的不同字体会有不同结果
*!*我的编辑框是宋体,9号字体,普通字体

*!* 设置不同的字体和大小看看
thisform.edit1.FontName=("微软雅黑")
thisform.edit1.FontSize=20
*!*
nwidth=0
i=0
cchar=""
cstr=""
nevenwidth=FONTMETRIC(6,thisform.edit1.FontName,thisform.edit1.FontSize,"N")
ctemp=thisform.edit1.Value
PUBLIC lines &&方便在命令窗口查看断行效果是否正确。
DIMENSION lines[1]
nindex=0
DO WHILE .t.
    i=i+1
    IF i>LEN(ctemp)
        nindex=nindex+1
        DIMENSION lines[nindex]
        lines[nindex]=ctemp
        EXIT
    ENDIF     
    cchar=SUBSTR(ctemp,i,1)
    IF ASC(cchar)>128
        i=i+1
    ENDIF
    cstr=SUBSTR(ctemp,1,i)
    nstrwidth=TXTWIDTH(cstr,thisform.edit1.FontName,thisform.edit1.FontSize,"N")
    nwidth=nhead+ntail+nscollbar+nstrwidth*nevenwidth
    IF nwidth>thisform.edit1.Width
*!*            i=i-1
        IF ASC(cchar)>128
            i=i-2 &&判断该行最后一个字符为汉字
        ELSE
            i=i-1 &&英文字母
        ENDIF
        nindex=nindex+1
        DIMENSION lines[nindex]
        lines[nindex]=SUBSTR(ctemp,1,i)
        ctemp=STRTRAN(ctemp,lines[nindex],"")
        IF EMPTY(ctemp)
            EXIT
        ELSE
            i=0
            LOOP
        ENDIF         
    ELSE
        LOOP
    ENDIF
ENDDO
thisform.text1.Value=LEN(lines[1])
thisform.text2.Value=ALEN(lines)



不知道中文中混有英文单词时的换行规则,仍有bug,但已经接近真相了。。。



[此贴子已经被作者于2025-11-5 21:55编辑过]

#7
schtg前天 06:33
#8
吹水佬前天 15:34
以下是引用sam_jiang在2025-11-5 19:49:36的发言:

不同的字体及size,会有不同的结果,雅黑就是个另类,大写小写的字符宽度都不一样的

只是字符串不同,其他都不变,都有不少问题。
只有本站会员才能查看附件,请 登录

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



#9
wcx_cc前天 18:26
模拟手工数行数,几乎解决全部问题,不妨试试看。
#10
sam_jiang昨天 15:32
回复 8楼 吹水佬
我猜想当编辑框中字符出现空格时,系统触发英文单词判定,并把单词列入判定换行的依据,以防止英文单词被分割,这个判定延续至双字节系统!有了这个猜想,解决它就不是一个问题了!我这两天完善这个算法试试看
#11
吹水佬昨天 15:53
回复 10楼 sam_jiang
逐行字符计算加硬换行,只要不超出右边界限,可以试试。
#12
sam_jiang昨天 16:02
回复 9楼 wcx_cc
一语惊醒梦中人,豁然开朗,确实模拟人工数行数是最为可行的方法!
#13
吹水佬昨天 17:14
以下是引用sam_jiang在2025-11-7 16:02:40的发言:

一语惊醒梦中人,豁然开朗,确实模拟人工数行数是最为可行的方法!

是找一行删一行吧,这做法算总行数。
如果只算编辑框内的行数还要准确计算每行的高。
#14
sam_jiang昨晚 20:46
回复 13楼 吹水佬
不要找一行删一行,我数行数是用下箭头键来数的,用home和end键快速定位行首和行尾,这样就简单了,我们只需用selstart属性就可以确定每次敲击下箭头后是否位置已变换,那么有效敲击的次数就是行数!同样利用Home和end键可以确定每行的字数!
#15
吹水佬2 小时前
回复 14楼 sam_jiang
这方法省去了字符串处理环节,效率较高。但原理都差不多,能准确计算总行数,要算编辑框内行数要适应不同字体和大小还有些细节问题。
1