| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
共有 2051 人关注过本帖, 1 人收藏
标题:RichTextbox控件如何根据自身宽、高,以及用户设定的字体、字号和行距,计算 ...
取消只看楼主 加入收藏
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:511
专家分:376
注 册:2013-10-4
结帖率:100%
收藏(1)
 问题点数:0 回复次数:36 
RichTextbox控件如何根据自身宽、高,以及用户设定的字体、字号和行距,计算1屏有几行?1行有几列?
看到吹版的这段代码,联想到以前我遇到的那个问题(一直都未能精确地解决):

程序代码:
        DECLARE long SendMessageW   IN user32 as SendMessageW2   long,long,long,string@
        DECLARE long SetWindowTextW IN user32 as SetWindowTextW2 long,string
        #define EM_GETLINE    0x00C4 
        nBufferSize = 2048    && 要足够大
        cBuffer     = BINTOC(nBufferSize,"4rs")+REPLICATE(0h00,nBufferSize+1)
        hEdit       = thisform.hEdit1.hwnd    &&编辑框句柄
        nLineNo     = 9                  &&要取的行号(通常是从0行起)
        nWordCount  = SendMessageW2(hEdit, EM_GETLINE, nLineNo, @cBuffer)
        SetWindowTextW2(hEdit, cBuffer)   && 显示结果


如标题所示:如何计算RichTextbox一屏可完整显示的行数?以及,一列能显示的字符个数?
原因:希望在不出现垂直滚动条的前提下,能够一屏显示完整内容,让用户不必频繁地上下翻滚(注:表单另外设计有翻页按钮)。
问DC,它给出的解答异常复杂,远非类似一个SendMessageW2(hEdit, EM_GETLINE, nLineNo, @cBuffer)就能解决得了的。
想想也是,“宋体,12,N”和“微软雅黑, 16, B”,同一屏能够完整显示的字符行数与列数,结果相差非常大的!

搜索更多相关主题的帖子: 显示 long RichTextbox 用户 计算 
2025-09-01 23:13
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:511
专家分:376
注 册:2013-10-4
收藏
得分:0 
以下是引用吹水佬在2025-9-2 08:35:18的发言:

没用过RichTextbox,随便拖一个试试,有个自动换行的问题,有无禁止自动换行的设置?
init事件:
this.text = REPLICATE("AaBbCcDdEeFfGgHhIiJjKkLlMmNn汉字1234567890",3)
遇到数字号码框不够宽时会自动换行?


确实,先前看到你们讨论“获取RichTextbox第N行文字内容”的帖子,恰好我也想到了这个变通的解决方案:
RichTextbox1.init事件:
this.text = REPLICATE(0hA1A1,10000)

然后,用你那一个API得到第1--3行的字符,再分别取lenc(),合计值/3得到平均值,这就是比较精确的一行有多少个字符了吧。
至于一屏有多少列,估计仍得用比较复杂的像素值来计算……

2025-09-02 10:29
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:511
专家分:376
注 册:2013-10-4
收藏
得分:0 
以下是引用sych在2025-9-2 07:18:47的发言:

Declare INTEGER SendMessage in WIN32API as sendmessage_n INTEGER hwnd , INTEGER wMsg , INTEGER wParam , INTEGER lParam
#defi EM_LINELENGTH 0xC1
MESSAGEBOX( SendMessage_n(thisform.Olecontrol5.hwnd, EM_LINELENGTH, 0,  0))
每行列数


这个API没问题,能准确返回一行汉字字符的个数!

[此贴子已经被作者于2025-9-2 13:30编辑过]

2025-09-02 11:17
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:511
专家分:376
注 册:2013-10-4
收藏
得分:0 
其实,计算一屏总行数,经反复实验,我有一个不太精确的解决方案:

程序代码:
*获取当前字体的行高
lnFontHeight = FONTMETRIC(1, thisform.RichTexBox1.Font.Name, thisform.RichTexBox1.Font.Size)

*计算每屏行数
lnLinesPerPage = INT(thisform.RichTexBox1.Height / lnFontHeight / 1.35)


至于那个神秘参数1.35,大致相当于行间距,是我随意设置的——有时候准,有时候不准,计算误差大约在0--2行之间。
不知诸位英雄,有没有更精确的解决方案?

2025-09-02 14:10
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:511
专家分:376
注 册:2013-10-4
收藏
得分:0 
以下是引用sych在2025-9-3 07:32:30的发言:

这个神奇的1.35猜测是96/72=1.33


不太清楚。我让DC猜测这个“校正参数”,我设置行距 lnlineSpacing = 行高的1.5倍,它给出的调整建议:

程序代码:
初始值:从 lc校正参数 = 0.08 开始测试
根据行间距调整:
1.0倍行距:校正参数 ≈ 0.04-0.06
1.5倍行距:校正参数 ≈ 0.08-0.12
2.0倍行距:校正参数 ≈ 0.12-0.16
根据字体大小调整:
小字体(8-10pt):减少校正参数
大字体(12-14pt+):增加校正参数

最终公式:
lnLinesPerPage = INT(thisform.RichTextBox1.Height / lnFontHeight / ;
                  (lnlineSpacing - (0.08 + (lnlineSpacing - 1) * 0.06)))


然而,结果并不理想。

2025-09-03 11:11
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:511
专家分:376
注 册:2013-10-4
收藏
得分:0 
以下是引用吹水佬在2025-9-3 11:39:56的发言:

行间距应该是编辑控件有定义的,不同字体和大小会有不同。
最好是自己能重新定义,那就是你说了算。


Richtextbox可以通过API设置行距,见我以前的讨论帖,还是您老人家给出的答案,亲,您不记得啦:
https://hrss.shandong.
2025-09-03 13:08
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:511
专家分:376
注 册:2013-10-4
收藏
得分:0 
以下是引用吹水佬在2025-9-3 13:55:00的发言:
与.gov的无关吧


搞笑搞笑,贴错了网址,应该是这一个的:

https://bbs.bc-cn.net/viewthread.php?tid=508544&page=1#pid2758685



2025-09-03 17:34
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:511
专家分:376
注 册:2013-10-4
收藏
得分:0 
以下是引用sych在2025-9-3 17:12:05的发言:

获取行数,如果最后一行没有完整显示,则不计算在内
Declare INTEGER SendMessage in WIN32API as sendmessage_n INTEGER hwnd , INTEGER wMsg , INTEGER wParam , integer lParam
#defi EM_GETFIRSTVISIBLELINE 0XCE
#defi EM_LINEINDEX  0xbb
#defi EM_POSFROMCHAR  0xd6
iFirstLine = SendMessage_n(thisform.Olecontrol5.hwnd, EM_GETFIRSTVISIBLELINE,0,0)
lh=0
lt=0
FOR i=0 TO 100
    cpFirst = SendMessage_n(thisform.Olecontrol5.hwnd,EM_LINEINDEX,iFirstLine+i,0)
    aa=SendMessage_n(thisform.Olecontrol5.hwnd, EM_POSFROMCHAR,cpFirst,0)
    aa=BITrSHIFT(aa,16)
    IF i>0
        IF aa=1
            i=i-1
            EXIT
        endif
        lh=MAX(aa-lt,lh)
        IF lh+aa>thisform.Olecontrol5.Height
            EXIT
        endif
    ENDIF
    lt=aa
next
MESSAGEBOX(i)
retu


太牛B了!英雄!
2025-09-03 17:35
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:511
专家分:376
注 册:2013-10-4
收藏
得分:0 
实战的话,其实是有一点点尴尬的:
必须填满Richtextbox1一整屏后,才能够得到正确的行、列结果。
表单初始化时,倘若客户区空白,那么只能返回0列和1行。
倒是可以设置visible = .F. 或 LockScreen = .T.,
先用垃圾将客户区填满,得到行、列值,然后再恢复现场。
不过,拖动改变表单大小,特别是拉大表单,导致Richtextbox客户区不再被填满,那么也将得到小于实际值的行的结果。

当然,解决方案也有,就是浪费一点资源:
复制一个一毛一样的Richtextbox2,
并设置Richtextbox2.left = - Richtextbox2.width - 10,再用垃圾将它填满。
计算行、列值,就用Richtextbox2;而真正用,则是Richtextbox1。

话说,我老人家是不是冰雪聪明来着?
2025-09-03 21:44
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:511
专家分:376
注 册:2013-10-4
收藏
得分:0 
以下是引用sych在2025-9-4 06:05:48的发言:

顺着你的思路走,可以用半角或者全角空格填满,再获取行列值,是不是可以省掉一个2


冰雪聪明如我,早想到这个思路啦!
不行,填充500个空格,似乎全挤在了一行。得到的返回值:
列=500
行=1

2025-09-04 07:35
快速回复:RichTextbox控件如何根据自身宽、高,以及用户设定的字体、字号和行距 ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.018865 second(s), 9 queries.
Copyright©2004-2025, BC-CN.NET, All Rights Reserved