You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi 11 Alexandria下32位VCL应用RTF转文本函数返回文件路径问题及替代方案咨询

RTF转纯文本函数问题及解决方案

一、原函数的核心问题

你的函数返回文件路径而非RTF内容,根源就在这一行代码:

MyStringStream := TStringStream.Create(RTF_FilePath);

你这里是把文件路径字符串直接作为流的内容创建了,完全没有读取指定路径下的RTF文件内容!后续RichEdit加载的只是路径文本,最后输出自然就是路径字符串了。

另外还有个细节逻辑问题:加载RTF内容时,应该先让RichEdit处于RTF模式(PlainText := False),加载完成后再切换到纯文本模式提取内容,原代码的顺序虽没直接报错,但逻辑上不够严谨。

二、修正后的TRichEdit实现(仍用无窗口控件)

如果还是想用TRichEdit的方式,只需要修正流的创建逻辑,正确读取RTF文件即可:

function RtfToText(const RTF_FilePath: string; ReplaceLineFeedWithSpace: Boolean): string;
var
  RTFConverter: TRichEdit;
  MyFileStream: TFileStream;
begin
  RTFConverter := TRichEdit.CreateParented(HWND_MESSAGE);
  try
    // 正确读取RTF文件到流中
    MyFileStream := TFileStream.Create(RTF_FilePath, fmOpenRead or fmShareDenyWrite);
    try
      RTFConverter.PlainText := False; // 确保以RTF模式加载内容
      RTFConverter.Lines.LoadFromStream(MyFileStream);
      RTFConverter.PlainText := True;
      RTFConverter.Lines.StrictDelimiter := True;
      if ReplaceLineFeedWithSpace then
        RTFConverter.Lines.Delimiter := ' '
      else
        RTFConverter.Lines.Delimiter := #13;
      Result := RTFConverter.Lines.DelimitedText;
    finally
      MyFileStream.Free;
    end;
  finally
    RTFConverter.Free;
  end;
end;

三、不依赖带父窗口TRichEdit的高效方案

如果你不想使用CreateParented(HWND_MESSAGE)创建的RichEdit控件,可以直接调用Windows的RichEdit底层API处理,完全不依赖VCL控件封装,更轻量化:

function RtfToText_NoRichEdit(const RTF_FilePath: string; ReplaceLineFeedWithSpace: Boolean): string;
var
  hRichEdit: HWND;
  StreamIn: EDITSTREAM;
  FileStream: TFileStream;
  Buffer: array[0..4095] of Char;
  function EditStreamCallback(dwCookie: DWORD_PTR; pbBuff: PByte; cb: LongInt; var pcb: LongInt): DWORD; stdcall;
  begin
    pcb := FileStream.Read(pbBuff^, cb);
    Result := 0;
  end;
begin
  Result := '';
  // 加载RichEdit库(这里使用RichEdit20W版本,兼容性较好)
  LoadLibrary('RICHED20.DLL');
  // 创建无窗口的RichEdit实例
  hRichEdit := CreateWindowEx(0, 'RICHEDIT20W', nil, ES_MULTILINE or ES_READONLY, 0, 0, 0, 0, HWND_MESSAGE, 0, HInstance, nil);
  if hRichEdit = 0 then Exit;
  try
    FileStream := TFileStream.Create(RTF_FilePath, fmOpenRead or fmShareDenyWrite);
    try
      // 设置流回调函数,将RTF文件内容读取到RichEdit中
      StreamIn.dwCookie := DWORD_PTR(FileStream);
      StreamIn.pfnCallback := @EditStreamCallback;
      SendMessage(hRichEdit, EM_STREAMIN, SF_RTF, LPARAM(@StreamIn));
      // 获取纯文本内容的长度
      SetLength(Result, SendMessage(hRichEdit, WM_GETTEXTLENGTH, 0, 0) + 1);
      // 读取纯文本内容
      SendMessage(hRichEdit, WM_GETTEXT, Length(Result), LPARAM(PChar(Result)));
      // 处理换行符替换需求
      if ReplaceLineFeedWithSpace then
        Result := StringReplace(Result, #13#10, ' ', [rfReplaceAll])
      else
        Result := StringReplace(Result, #10, '', [rfReplaceAll]); // 统一换行符为#13
    finally
      FileStream.Free;
    end;
  finally
    DestroyWindow(hRichEdit);
  end;
end;

这个方案直接调用底层API,没有VCL控件带来的额外开销,效率更高,也完全符合你“不使用带父窗口TRichEdit控件”的需求。如果想更简洁,也可以考虑使用开源的纯Pascal RTF解析类,但上述API方案已经足够高效且原生。

内容的提问来源于stack exchange,提问作者user1580348

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 11:12:44