参考示例,没有精准测试。

程序代码:
CLEAR
CLEAR ALL
PUBLIC cDefPath
cDefPath = ADDBS(JUSTPATH(SYS(16)))
SET DEFAULT TO (cDefPath)
** int GetRichEditCharsW(HWND hRichEdit, LPCWSTR text, char* cFontName, int nFontSize)
DECLARE integer GetRichEditCharsW IN TextMetric long,string@,string@,integer
** int SetRichEditLineHeight(HWND hRichEdit, int nPixels)
DECLARE integer SetRichEditLineHeight IN TextMetric long,integer
** int GetRichEditLineCount(HWND hRichEdit, char* pFontName, int nFontSize)
DECLARE integer GetRichEditLineCount IN TextMetric long,string@,integer
of = CREATEOBJECT("form1")
of.show(1)
CLEAR ALL
RETURN
DEFINE CLASS form1 as Form
width = 420
height = 420
AllowOutput = .f.
AutoCenter = .t.
ADD OBJECT edit as OleControl WITH left=10,top=10,width=400,height=400,;
OleClass="RICHTEXT.RichtextCtrl.1"
PROCEDURE init
#if 1
this.edit.font.name = "宋体"
#else
this.edit.font.name = "微软雅黑"
#endif
this.edit.font.size = 12
** 行高 = 字高 + 行间距
nLineHeight = FONTMETRIC(1,this.edit.font.name, MTON(this.edit.font.size)) + 5
SetRichEditLineHeight(this.edit.hWnd, nLineHeight) && 设置行高
** 获取总行数
nLineCount = GetRichEditLineCount(this.edit.hWnd, this.edit.font.name, MTON(this.edit.font.size))
this.Caption = " FontName: "+this.edit.font.name;
+ " FontSize: "+TRANSFORM(MTON(this.edit.font.size));
+ " LineCount: "+TRANSFORM(nLineCount)
** 显示一页字(测试只显示一页)
cText = REPLICATE("AaBbCcDdEeFfGgHhIiJjKk字字字字1234567890",100)
cStr = "" && 一页字串
nCount = 0 && 行计数
DO WHILE !EMPTY(cText) AND nCount < nLineCount
** 获取一行字串
nChars = GetRichEditCharsW(this.edit.hWnd, STRCONV(cText,5), this.edit.font.name, MTON(this.edit.font.size))
IF nChars < LENC(cText) && 如果不是最后一行
nChars = nChars - 1 && 减一个字,忽略边际不完整的字
ENDIF
cStr = cStr + LEFTC(cText,nChars) + 0h0D0A && 添加一行
cText = SUBSTRC(cText, nChars+1) && 下一行开始
nCount = nCount + 1 && 行计数
ENDDO
** 显示输出
this.edit.text = "" && test方法会清除字体设置信息
SetRichEditLineHeight(this.edit.hWnd, nLineHeight) && 重新设置字体信息
this.edit.SelText = cStr
this.edit.selstart = 0
ENDPROC
ENDDEFINE

程序代码:
/*
库文件 gdi32.lib
*/
#define DLLIMPORT_C extern "C" __declspec(dllexport)
#include <windows.h>
#include <richedit.h>
//获取 Rich Edit 字体信息并创建字体对象句柄
HFONT GetRichEditFontHandle(HWND hRichEdit, char* pFontName, int nFontSize)
{
HDC hdc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
CHARFORMAT cf;
ZeroMemory(&cf, sizeof(CHARFORMAT));
cf.cbSize = sizeof(CHARFORMAT);
// 获取当前选择文本的字符格式
SendMessage(hRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
// 从CHARFORMAT创建字体对象
HFONT hFont = CreateFont(
-MulDiv(nFontSize, GetDeviceCaps(hdc,LOGPIXELSY), 72), //转换单位
0, 0, 0,
(cf.dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL,
(cf.dwEffects & CFE_ITALIC) ? TRUE : FALSE,
(cf.dwEffects & CFE_UNDERLINE) ? TRUE : FALSE,
(cf.dwEffects & CFE_STRIKEOUT) ? TRUE : FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE,
pFontName
);
DeleteDC(hdc);
return hFont;
}
//获取 Rich Edit 在客户区一行字串的字数
DLLIMPORT_C int GetRichEditCharsW(HWND hRichEdit, LPCWSTR text, char* pFontName, int nFontSize)
{
//获取控件尺寸和边距
RECT rect;
GetClientRect(hRichEdit, &rect);
int editWidth = rect.right - rect.left;
DWORD margins = SendMessage(hRichEdit, EM_GETMARGINS, 0, 0);
editWidth -= (LOWORD(margins) + HIWORD(margins));
HDC hdc = GetDC(hRichEdit);
//获取当前字体
HFONT hFont = GetRichEditFontHandle(hRichEdit, pFontName, nFontSize);
HFONT hOldFont = (HFONT)SelectObject(hdc, hFont);
int len = lstrlenW(text);
int nChars = 0;
SIZE sz;
//计算一行的字数
for (int i = 1; i <= len; i++) {
if (!GetTextExtentPoint32W(hdc, text, i, &sz)) break;
if (sz.cx > editWidth) break;
nChars = i;
}
SelectObject(hdc, hOldFont);
ReleaseDC(hRichEdit, hdc);
return nChars;
}
//设置 Rich Edit 行高
DLLIMPORT_C int SetRichEditLineHeight(HWND hRichEdit, int nPixels)
{
//获取当前设备DPI
HDC hdc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
int dpi = GetDeviceCaps(hdc, LOGPIXELSY);
DeleteDC(hdc);
//设置行高
PARAFORMAT2 pf;
ZeroMemory(&pf, sizeof(PARAFORMAT2));
pf.cbSize = sizeof(PARAFORMAT2);
pf.dwMask = PFM_LINESPACING;
pf.bLineSpacingRule = 4; //精确行高
pf.dyLineSpacing = (nPixels * 20 * 72) / dpi; //像素转换为缇
return SendMessage(hRichEdit, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
}
//获取 Rich Edit 客户区的行数
DLLIMPORT_C int GetRichEditLineCount(HWND hRichEdit, char* pFontName, int nFontSize)
{
HDC hdc = GetDC(hRichEdit);
// 强制重新获取当前字体
HFONT hFont = GetRichEditFontHandle(hRichEdit, pFontName, nFontSize);
HFONT hOldFont = (HFONT)SelectObject(hdc, hFont);
//获取当前设备DPI
HDC hdc2 = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
int dpi = GetDeviceCaps(hdc2, LOGPIXELSY);
// 获取行高
PARAFORMAT2 pf;
ZeroMemory(&pf, sizeof(PARAFORMAT2));
pf.cbSize = sizeof(PARAFORMAT2);
pf.dwMask = PFM_LINESPACING;
SendMessage(hRichEdit, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
int lineHeight = 0;
if (pf.dyLineSpacing > 0)
{
lineHeight = (pf.dyLineSpacing * dpi) / (20 * 72); // 转换为像素值
}
DeleteDC(hdc2);
SelectObject(hdc, hOldFont);
ReleaseDC(hRichEdit, hdc);
// 计算客户区行数
RECT rc;
GetClientRect(hRichEdit, &rc);
return rc.bottom / lineHeight;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
return TRUE;
}