注册 登录
编程论坛 VFP论坛

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

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

程序代码:

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

113 回复
#102
wcx_cc2025-09-16 23:16
看见版主和高手们的讨论很热烈,备受鼓舞!在多年以前,曾受吹版主的启发,对 edit 内的文字资料,不管是汉字的,字母的,数字的混合文本,也不管是每行有无回车键或换行符,或文字占满一行后的自动换行,只要是肉眼观察到的独立一行(注:是我们所看到的页面上的一行一行),能够精确提取出所观察到的每一行,或每一行的每个字符(汉字或单字符),实现的目的,是为了能够将每一行或每行的每个字符放入到一张dbf表内,能够实现精确打印页面,防止打印不全或漏打,可以看看吹版主早先的edit 读行数,看看有没有可借签之处。
#103
easyppt2025-09-18 08:54
这个帖子好热哦,RichTextbox 如雷贯耳,应该是VFP富文本交互最好的控件了,学习了,谢谢各位大佬!
#104
吹水佬2025-09-20 17:30
回复 94楼 cssnet
如果想在VFP编辑显示MD,可以试试用HTML+JS,一边编辑一边预览。
VFP用WEB控件运行.HTML也简单,这方面的参考示例应该有不少,可以搜搜看。
#105
cssnet2025-09-21 17:47
以下是引用吹水佬在2025-9-20 17:30:58的发言:

如果想在VFP编辑显示MD,可以试试用HTML+JS,一边编辑一边预览。
VFP用WEB控件运行.HTML也简单,这方面的参考示例应该有不少,可以搜搜看。


依我的理解,MD 是一种“轻量级”、“微量级”的格式标记,介于 TXT 与 HTML/RTF 之间,且更偏向于 TXT。MD 同时具备了 TXT 与 HTML 的一切优点,且无后者的复杂臃肿,是一种相当完美的现代格式文档。

至于编辑、预览 MD,我却不想花费太大精力;若无法简单实现,则直接放弃可也。毕竟,径直用Editbox或RichtextBox 显示 MD 源文档都行—— MD 不像 HTML/RTF,它的那些简单标记,即便不作任何渲染,也是完全可读的。

俗话说:又想马儿快快跑,又想马儿不吃草——没错儿,这说的正是我老人家!
#106
吹水佬2025-09-24 10:58
回复 105楼 cssnet
MD通用的就几个标签,用vfp的字串替换函数应该就可以做个简单的解析器。

[此贴子已经被作者于2025-9-25 10:54编辑过]

#107
easyppt2025-09-24 11:07
md也是标记语言,也支持通过CSS定义样式,只不过它的标签相对比较少。
代码标签支持的语言很多,这个是亮点,所以程序员用MD的很多,夸张点说就是为程序员写说明文档量身打造的
#108
cssnet2025-09-26 11:45
以下是引用吹水佬在2025-9-24 10:58:30的发言:

MD通用的就几个标签,用vfp的字串替换函数应该就可以做个简单的解析器。


因为一直琢磨的都是“MD <==> RTF”之间的可逆转换,倘若用VFP原生替换函数去手动处理,必然涉及到RTF标记的解析,而这绝对是一道鸿沟!
——事关,RTF太TM复杂、太TM臃肿啦!
网上其实有现成的RTF解析的C代码,然而,从最底层一步一步解析RTF,那绝非普通人能玩得转的。

更多的,则是参照Pandoc的做法,将整个转换过程,分割成3大块:
① From -> ② 转换 -> ③ TO
其中,①和③支持一大堆杂七杂八的格式,而②是相对独立的转换模块。
如此一来,我们根本无法简单地抽取出所需模块:
① From MD -> ② 转换 -> ③ TO RTF
① From RTF -> ② 转换 -> ③ TO MD
它打了一个大包,千头万绪的,没人能从中切分出一小块蛋糕来。

难!——就一个字。

#109
吹水佬2025-09-26 15:53
回复 108楼 cssnet
关键是你要多强大的MD,MD有些也有点强大,甚至用嵌入其他代码来实现一些强大的功能。
简单的MD解析应该不难,只要找到标签对应关系就可以吧?
#110
吹水佬2025-09-26 15:57
MD的初衷只是类似一个极精简的HTML,现在是不是商业价值的问题,好像显得有点复杂了。
#111
cssnet2025-10-08 22:37
以下是引用吹水佬在2025-9-5 07:36:15的发言:
LockScreen 是 Lock vfp窗口,对 richedit 可能无效。
试试:
SendMessage(hRichEdit, WM_SETREDRAW, 0, 0)    && Lock
SendMessage(hRichEdit, WM_SETREDRAW, 1, 0)    && UnLock


大佬啊,这两行代码,表面上好用,实战可能会有(大)麻烦!
今天晕头晕脑地调试了整整一天,Richtextbox表现一直很不正常,随机性地抛出异常。
经常性地表现为:
在 Lock/UnLock 代码之后,Richtextbox可能无法以代码激活,呈现灰色,需手动点击一次才能够唤醒。
一开始一直以为是某个深藏不露的逻辑错误,拼命地Debug,拼命地查错,一直无办法解决……直至晚上10点,一拍脑门,这才想起来!——注释掉了这一组 Lock/UnLock 后,整个世界一下子豁然清朗了!
原来是它们搞的鬼哇!
吐血!
慎用!慎用!慎用!
——说三遍。
#112
吹水佬2025-10-08 23:24
回复 111楼 cssnet
WM_SETREDRAW消息实质是从窗口中删除或添加 WS_VISIBLE 样式。
MS在WM_SETREDRAW消息说明中有这样一段:
“最后,应用程序可以调用 RedrawWindow(hWnd, NULL, NULL, RDW_ERASE |RDW_FRAME |RDW_INVALIDATE |RDW_ALLCHILDREN) 会重新绘制”
看看有无作用

#113
cssnet2025-10-09 11:49
以下是引用吹水佬在2025-10-8 23:24:41的发言:

WM_SETREDRAW消息实质是从窗口中删除或添加 WS_VISIBLE 样式。
MS在WM_SETREDRAW消息说明中有这样一段:
“最后,应用程序可以调用 RedrawWindow(hWnd, NULL, NULL, RDW_ERASE |RDW_FRAME |RDW_INVALIDATE |RDW_ALLCHILDREN) 会重新绘制”
看看有无作用


确实很可能是Redraw的问题。
你这么一说,我想起来啦:
许多年以前,我们曾套用网上的开源 VB6 代码,编译出一个 Richtextbox 的替代品,以便更好地支持Unicode。VB6 的代码,说实话,仅限于“勉强看懂”水平,修修补补,根据自己需求定制一下个别方法函数,勉强倒也还凑合;若正儿八经拿 VB6 去写控件,那做不到!那控件同样也有这个Redraw问题:绝对不能改Visible!一改,就变成了僵尸,无论如何再也唤不醒了!
当时我们自己实在没能力修复这个Bug,无人精通 VB6。最后想出来的解决办法比较搞笑:
若需 .Visible = .F. ,就设置:
with this
    .left = 1
    .top = 1
    .width = 1
    .height = 1
endwith
理论上,应该不会有人能留意到,在窗口左上角有个小黑点——那是一片海,一个世界!

总结一下:
自己编写可视化控件,有可能会遇到无数奇奇怪怪、匪夷所思的Bug,你根本想都想不到的,故而上次你一晚上弄一组控件出来,问“有没有搞头”?——当然有搞头!不过——重点是这个“不过”——事情恐怕没那么简单。
讲真,很鬼复杂滴!


#114
吹水佬2025-10-09 20:12
以下是引用cssnet在2025-10-9 11:49:31的发言:
总结一下:
自己编写可视化控件,有可能会遇到无数奇奇怪怪、匪夷所思的Bug,你根本想都想不到的,故而上次你一晚上弄一组控件出来,问“有没有搞头”?——当然有搞头!不过——重点是这个“不过”——事情恐怕没那么简单。
讲真,很鬼复杂滴!

主要是VFP的UI有自己的一套,对第三方的东西有时不那么“友好”。
如那个“有没有搞头”,如果直接在vfp的表单中用CreateWindow创建子控件,问题就更复杂不好处理。

123