Delphi 10.3中TJvRichEdit文本设置异常问题求助
问题概述
从Delphi 2007迁移至10.3(同版本JVCL),Firebird 3.0/64的BLOB文本字段存储RTF内容。使用非数据库版TJvRichEdit加载table.BLOBField.AsString后,Delphi 2007中JvRichEditcontrol.Text返回解析后的纯文本,而10.3中返回完整RTF源码,导致ConvertToHtmlStrings生成的HTML嵌入RTF标签。但子类TJvDBRichEdit可正常解析显示,说明存在正确的加载逻辑。
核心原因
Delphi 2007使用ANSI字符串,TJvRichEdit的Text属性赋值时会自动识别ANSI编码的RTF内容并解析为富文本;而Delphi 10.3采用UnicodeString,直接赋值Text时,控件将内容视为纯文本而非RTF格式,因此不会触发解析逻辑,直接保留原始RTF代码。
TJvDBRichEdit的正常工作,是因为它并非直接赋值Text,而是通过数据库字段的专用加载流程,调用了RTF解析的底层接口。
解决方案
方法1:通过流加载RTF内容
将BLOB字段内容存入内存流,再用LoadFromStream指定RTF格式加载:
Var HTML : TStringList; MS: TMemoryStream; begin MS := TMemoryStream.Create; try table.BLOBField.SaveToStream(MS); MS.Position := 0; JvRichEditcontrol.PlainText := False; JvRichEditcontrol.LoadFromStream(MS, TStreamFormat.sfRTF); JvRichEditToHtml.ConvertToHtmlStrings(JvRichEditcontrol, HTML); finally MS.Free; end; end;
方法2:调用RichEdit底层API加载
使用EM_STREAMIN消息直接传入RTF内容,绕过Text属性的赋值逻辑:
Var HTML : TStringList; EditStream: TEditStream; RtfContent: string; function EditStreamCallback(dwCookie: DWORD_PTR; pbBuff: PByte; cb: LongInt; var pcb: LongInt): DWORD; stdcall; begin pcb := Min(cb, Length(RtfContent) - dwCookie); if pcb > 0 then begin Move(PByte(@RtfContent[dwCookie + 1])^, pbBuff^, pcb); Result := 0; end else Result := 1; end; begin RtfContent := table.BLOBField.AsString; EditStream.dwCookie := 0; EditStream.pfnCallback := @EditStreamCallback; JvRichEditcontrol.PlainText := False; SendMessage(JvRichEditcontrol.Handle, EM_STREAMIN, SF_RTF, LPARAM(@EditStream)); JvRichEditToHtml.ConvertToHtmlStrings(JvRichEditcontrol, HTML); end;
方法3:模拟TJvDBRichEdit的加载逻辑
复用JVCL内部的加载逻辑,直接操作控件的Lines流:
Var HTML : TStringList; begin JvRichEditcontrol.PlainText := False; if table.BLOBField.IsBlob then begin JvRichEditcontrol.Lines.BeginUpdate; try JvRichEditcontrol.Clear; table.BLOBField.SaveToStream(JvRichEditcontrol.Lines.LoadedStream); JvRichEditcontrol.Lines.LoadedStream.Position := 0; JvRichEditcontrol.Lines.LoadFromStream(JvRichEditcontrol.Lines.LoadedStream, TStreamFormat.sfRTF); finally JvRichEditcontrol.Lines.EndUpdate; end; end; JvRichEditToHtml.ConvertToHtmlStrings(JvRichEditcontrol, HTML); end;
验证结果
采用上述任意方法后,TJvRichEdit会正确解析RTF内容,JvRichEditcontrol.Text返回纯文本,ConvertToHtmlStrings生成带<b>、<i>等格式标签的预期HTML。
内容的提问来源于stack exchange,提问作者alvaroc

