在Delphi XE8和Delphi 7之间显示RTF-Text时出现问题

问题描述 投票:1回答:1

我在两个delphi版本之间显示RTF格式的文本时遇到问题。

TDBRichEdit-Control和TRichEdit-Control似乎无法解析所提供的RTF文本。

有时似乎要让它在XE8中工作,您只需将TDBRichEdit连接到数据集中的相应字段,但同样的方法会弄乱Delphi 7版本。

所以我们认为我们通过Code来处理这个问题。基本上我们用普通的TRichEdits替换TDBRichEdits并通过流提供RTF。

textstream:=TStringStream.Create(CDS.FieldByName('TEXT').AsString);  
try                                                                                   
  RichEditFAPLAN.Lines.Clear();                                            
  RichEditFAPLAN.Lines.LoadFromStream(textStream);                         
finally                                                                    
  textstream.Free();                                                       
end;

直到大约1小时前我才决定将上面的代码移到它自己的全局可用函数中。

procedure StreamRichTextTo(ARichEdit:TCustomRichEdit; ADataSet:TDataSet; AFieldName:String);
var
  ws:WideString;
  Stream:TStringStream;
begin
  ARichEdit.Lines.Clear();
  if (ADataSet=nil) or (ADataSet.FindField(AFieldName)=nil) or (ADataSet.FieldByName(AFieldName).IsNull) then exit;

  ws:=UTF8Decode(ADataSet.FieldByName(AFieldName).AsString);
  Stream:=TStringStream.Create(ws);
  try
    Stream.Position:=0;
    ARichEdit.Lines.LoadFromStream(Stream);
  finally
    Stream.Free();
  end;
end;

我尝试了不同的代码变体。使用MemoryStream,Widestring,UTF8编码,AnsiString等等。

procedure StreamRichTextTo(ARichEdit:TCustomRichEdit; ADataSet:TDataSet; AFieldName:String);
var
  {$IFDEF VER150}
    ws:WideString;
    Stream:TStringStream;
  {$ELSE}
    s:AnsiString;
    //Stream:TMemoryStream;
    Stream:TStringStream;
  {$ENDIF}
begin
  ARichEdit.Lines.Clear();
  if (ADataSet=nil) or (ADataSet.FindField(AFieldName)=nil) or (ADataSet.FieldByName(AFieldName).IsNull) then exit;
  {$IFDEF VER150}
    ws:=UTF8Decode(ADataSet.FieldByName(AFieldName).AsString);
    Stream:=TStringStream.Create(ws);
  {$ELSE}
    {
    s:=ADataSet.FieldByName(AFieldName).AsAnsiString;
    Stream:=TMemoryStream.Create();
    Stream.Clear();
    Stream.Write(PAnsiChar(s)^,length(s));
    }
    s:=ADataSet.FieldByName(AFieldName).AsAnsiString;
    Stream:=TStringStream.Create(s,TEncoding.UTF8);
    //Stream.WriteString(s);
    Stream.Position:=0;
  {$ENDIF}
  try
    ARichEdit.Lines.LoadFromStream(Stream);
  finally
    Stream.Free();
  end;
end;

一切都无济于事,XE-RTF-Text总是看起来像这样或简单'':

{\rtf1\fbidis\ansi\ansicpg1252\deff0{\fonttbl{\f0\fnil\fcharset0 arial;}{\f1\fswiss\fprq2\fcharset0 Arial;}{\f2\fnil arial;}}
\viewkind4\uc1\pard\ltrpar\lang1031\f0\fs20 Gie\'dftemp.: \tab 1350 - 1370 \'b0C
\par \ul\f1 Form fest verklammern und belasten
\par \ulnone\f0 
\par \tab\tab\f2 
\par }

更重要的是,我回顾过的带有“文本流”的原始代码也不再适用了。

我正在寻找的是一种代码解决方案,可以在不同的IDE版本之间正确处理RTF-Text。

编辑:

这是一个示例项目代码。问题是,这个项目一切正常。我不知道为什么相同的代码不再适用于我们的软件,我无法重现它。

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, Data.DB,
  Datasnap.DBClient;

type
  TForm1 = class(TForm)
    REGoal: TRichEdit;
    Button1: TButton;
    CDS: TClientDataSet;
    RESource: TRichEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure StreamRichTextTo(ARichEdit:TRichEdit; ADataSet:TDataSet; AFieldName:String);
var
  Stream:TStringStream;
  //{$IFDEF VER150}
  ws:WideString;
  //{$ELSE}
  //{$ENDIF}
begin
  ARichEdit.Lines.Clear();
  if (ADataSet=nil) or (ADataSet.FindField(AFieldName)=nil) or (ADataSet.FieldByName(AFieldName).IsNull) then exit;
  try
    //{$IFDEF VER150}
      ws:=UTF8Decode(ADataSet.FieldByName(AFieldName).AsString);
      Stream:=TStringStream.Create(ws);
    //{$ELSE}
    //  Stream:=TStringStream.Create(ADataSet.FieldByName(AFieldName).AsString);
    //{$ENDIF}
    ARichEdit.Lines.LoadFromStream(Stream);
  finally
    Stream.Free();
  end;
end;

(*  Copy this to RESource

{\rtf1\ansi\ansicpg1252\deff0{\fonttbl{\f0\fnil\fcharset0 arial;}{\f1\fnil arial;}}
\viewkind4\uc1\pard\lang1031\f0\fs20 Erste Form ist eine Zulegekontrolle durchzuf\fchren.
\par
\par
\par \f1
\par }

*)


procedure TForm1.Button1Click(Sender: TObject);
var
  Stream:TStringStream;
begin
  if CDS.FindField('TEXT')=nil then
  begin
    CDS.FieldDefs.Add('TEXT',ftWideString,4096);
    CDS.CreateDataSet();
  end;

  CDS.Edit();
  CDS.FieldByName('TEXT').AsString:=RESource.text;
  CDS.Post();

  StreamRichTextTo(REGoal,CDS,'TEXT');
end;
  • 只需创建一个新的Form1
  • 添加2个TRichEdits,一个称为RESource,另一个称为REGoal
  • 添加一个TClientDataSet并将其命名为CDS
  • 添加一个按钮
  • 将OnClick过程分配给按钮

我将尝试在D7中创建项目并将其移植到XE8,也许这将重现效果。

编辑2:在Delphi 7中创建项目然后在XE8中打开它会产生相同的结果。

我的猜测是,当Database-Value被分配给String-Variable(或直接传递到流中)时会发生一些事情,这就是我无法重现错误的原因。

也许数据库有问题。它是一个带有VarChar-Field的Firebird 3.0数据库

delphi-7 rtf delphi-xe8 richtext
1个回答
0
投票

这是代码的工作版本。由于编辑器中存在错误,显然RTF-Code本身存在问题

procedure StreamRichTextTo(ARichEdit:TRichEdit; ADataSet:TDataSet; AFieldName:String);
var
  {$IFDEF VER150}
    ws:WideString;
  {$ELSE}
    ws:String;
  {$ENDIF}
  Stream:TStringStream;
begin
  ARichEdit.Lines.Clear();
  if (ADataSet=nil) or (ADataSet.FindField(AFieldName)=nil) or (ADataSet.FieldByName(AFieldName).IsNull) then exit;

  {$IFDEF VER150}
    ws:=UTF8Decode(ADataSet.FieldByName(AFieldName).AsString);
  {$ELSE}
    ws:=ADataSet.FieldByName(AFieldName).AsString;
  {$ENDIF}
  Stream:=TStringStream.Create(ws);
  try
    ARichEdit.Lines.LoadFromStream(Stream);
  finally
    Stream.Free();
  end;
end;
© www.soinside.com 2019 - 2024. All rights reserved.