注册 登录
编程论坛 VFP论坛

RichTextbox控件如何根据自身宽、高,以及用户设定的字体、字号和行距,计算1屏有几行?1行有几列?

cssnet 发布于 前天 23:13, 178 次点击
看到吹版的这段代码,联想到以前我遇到的那个问题(一直都未能精确地解决):

程序代码:

        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”,同一屏能够完整显示的字符行数与列数,结果相差非常大的!

11 回复
#2
sych昨天 06:43
这个问题挑战性大,每行可显示的字符数可以变通获取,但不同的字符宽度不同,不知道会不会有所不同
#3
sych昨天 07:18
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))
每行列数

#4
sych昨天 07:20
不同的字符占用的空间不同,这个值会发生变化
#5
吹水佬昨天 08:35
没用过RichTextbox,随便拖一个试试,有个自动换行的问题,有无禁止自动换行的设置?
init事件:
this.text = REPLICATE("AaBbCcDdEeFfGgHhIiJjKkLlMmNn汉字1234567890",3)
遇到数字号码框不够宽时会自动换行?
只有本站会员才能查看附件,请 登录



#6
cssnet昨天 10:29
以下是引用吹水佬在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得到平均值,这就是比较精确的一行有多少个字符了吧。
至于一屏有多少列,估计仍得用比较复杂的像素值来计算……

#7
wxzd123昨天 11:04
太好了,跟着楼主学习了
#8
wxzd123昨天 11:05
我弄了半天也没搞明白,这回测试一下楼主的代码
#9
wxzd123昨天 11:10
RichTextbox排版好,可vfp的编辑框Edit1排版不好,但能透明,我想RichTextbox排版完把每行后面加个回车符,然后用Edit1显示,可是没有实现。
#10
cssnet昨天 11:17
以下是引用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编辑过]

#11
cssnet昨天 14:10
其实,计算一屏总行数,经反复实验,我有一个不太精确的解决方案:

程序代码:

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

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


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

#12
吹水佬昨天 16:24
GDI绘制文本有设置行间距和字间距的相关函数
思路:
1..获取字串高+行间距,确定行数。
2..获取字串宽,确定一行字数。
行间距可以试试FONTMETRIC(5,.....)+n,n(1,2,.....)试试。
字串宽就有点麻烦,可尝试调用API函数GetTextExtentPoint32W()最后一个参数(SIZE结构)是返回字串输出的x,y座标,x就是字串的宽,y是字高。



1