Delphi 64位将RTF流插入RichEdit。

huangapple go评论56阅读模式
英文:

Delphi 64 bits Insert rtf stream into richedit

问题

I try to insert a rtf inside a richedit (specifically a rtf saved in database, and then inserted in the current richedit control at the selection point).

The code below works in 32 bits. But was not able to make it work in 64 bits, even by reading different replies in google in other languages.

I think I have somewhere the wrong size of some types.

Thanks already for helping me.

Version Delphi 10.4 (But I don't think it is relevant)

type
  TEditStreamCallBack = function(dwCookie: Longint; pbBuff: PByte;  
    cb: Longint; var pcb: Longint): DWORD;  
  stdcall;

  TEditStream = record
    dwCookie: Longint;
    dwError: Longint;
    pfnCallback: TEditStreamCallBack;
  end;

  TpRichEditUtils = class
  public
    class procedure RTFInsertStream(const ARichEdit : TRichEdit; const AStream: TStream);
  end;

implementation

uses
  Winapi.RichEdit, SysUtils;

function EditStreamReader(dwCookie: DWORD; pBuff: Pointer; cb: LongInt; pcb: PLongInt): DWORD; stdcall;
begin
  Result := $0000;  // assume no error
  try
    pcb^ := TStream(dwCookie).Read(pBuff^, cb); // read data from stream
  except
    Result := $FFFF;  // indicates error to calling routine
  end;
end;

class procedure TpRichEditUtils.RTFInsertStream(const ARichEdit : TRichEdit; const AStream: TStream);
var
  EditStream: TEditStream;  // callback used to read inserted RTF
begin
  ARichEdit.Lines.BeginUpdate;
  try
    // Make sure rich edit is large enough to take inserted code
    ARichEdit.MaxLength := ARichEdit.MaxLength + AStream.Size;
    // Stream in the RTF via EM_STREAMIN message
    EditStream.dwCookie := DWORD(AStream);
    EditStream.dwError := $0000;
    EditStream.pfnCallback := @EditStreamReader;
    ARichEdit.Perform(
      EM_STREAMIN,
      SFF_SELECTION or SF_RTF or SFF_PLAINRTF, LPARAM(@EditStream)
    );
    // Report any errors as a bug
    if EditStream.dwError <> $0000 then
      raise Exception.Create('RTFInsertStream: Error inserting stream');
  finally
    ARichEdit.Lines.EndUpdate;
  end;
end;

OStream := TStringStream.Create(ODmRemarqueStandard.REMSTD_TEXTE);
try
  TpRichEditUtils.RTFInsertStream(TcxRichInnerEdit(EdtConditionGenerale.InnerControl), OStream);
finally
  FreeAndNil(OStream)
end;

I tried changing the dwCookie: Longint to DWORD_PTR, and tried other things, but always access violation.

英文:

I try to insert a rtf inside a richedit (specifically a rtf saved in database, and then inserted in the current richedit control at the selection point).

The code below works in 32 bits. But was not able to make it work in 64 bits, even by reading different replies in google in other languages.

I think I have somewhere the wrong size of some types.

Thanks already for helping me.

Version Delphi 10.4 (But I don't think it is relevant)

type
  TEditStreamCallBack = function(dwCookie: Longint; pbBuff: PByte;  
    cb: Longint; var pcb: Longint): DWORD;  
  stdcall;

  TEditStream = record
    dwCookie: Longint;
    dwError: Longint;
    pfnCallback: TEditStreamCallBack;
  end;

  TpRichEditUtils = class
  public
    class procedure RTFInsertStream(const ARichEdit : TRichEdit; const AStream: TStream);
  end;

implementation

uses
  Winapi.RichEdit, SysUtils;

function EditStreamReader(dwCookie: DWORD; pBuff: Pointer; cb: LongInt; pcb: PLongInt): DWORD; stdcall;
begin
  Result := $0000;  // assume no error
  try
    pcb^ := TStream(dwCookie).Read(pBuff^, cb); // read data from stream
  except
    Result := $FFFF;  // indicates error to calling routine
  end;
end;

class procedure TpRichEditUtils.RTFInsertStream(const ARichEdit : TRichEdit; const AStream: TStream);
var
  EditStream: TEditStream;  // callback used to read inserted RTF
begin
  ARichEdit.Lines.BeginUpdate;
  try
    // Make sure rich edit is large enough to take inserted code
    ARichEdit.MaxLength := ARichEdit.MaxLength + AStream.Size;
    // Stream in the RTF via EM_STREAMIN message
    EditStream.dwCookie := DWORD(AStream);
    EditStream.dwError := $0000;
    EditStream.pfnCallback := @EditStreamReader;
    ARichEdit.Perform(
      EM_STREAMIN,
      SFF_SELECTION or SF_RTF or SFF_PLAINRTF, LPARAM(@EditStream)
    );
    // Report any errors as a bug
    if EditStream.dwError &lt;&gt; $0000 then
      raise Exception.Create(&#39;RTFInsertStream: Error inserting stream&#39;);
  finally
    ARichEdit.Lines.EndUpdate;
  end;
end;

OStream := TStringStream.Create(ODmRemarqueStandard.REMSTD_TEXTE);
try
  TpRichEditUtils.RTFInsertStream(TcxRichInnerEdit(EdtConditionGenerale.InnerControl), OStream);
finally
  FreeAndNil(OStream)
end;

I tried changing the dwCookie: Longint to DWORD_PTR. and tried other things, but always access violation.

答案1

得分: 1

Your TEditStreamCallBackEditStreamReader 声明不匹配。

此外,在32位和64位版本中都将cookie处理为32位整数是错误的。在32位版本中,它需要是32位整数,在64位版本中,它需要是64位整数。Win32 API声明cookie为 DWORD_PTR 就是为了这个目的。

TEditStreamCallBackTEditStream 已经在 Winapi.RichEdit 单元中声明,您不需要在您的代码中手动声明它们。

请尝试使用以下代码代替:

uses
  Winapi.RichEdit, SysUtils;

function EditStreamReader(dwCookie: DWORD_PTR; pbBuff: PByte; cb: Longint; var pcb: Longint): Longint; stdcall;
begin
  Result := 0;  // 假设没有错误
  try
    pcb := TStream(dwCookie).Read(pBuff^, cb); // 从流中读取数据
  except
    Result := -1;  // 表示错误给调用程序
  end;
end;

class procedure TpRichEditUtils.RTFInsertStream(const ARichEdit : TRichEdit; const AStream: TStream);
var
  EditStream: TEditStream;  // 用于读取插入的RTF的回调
begin
  ARichEdit.Lines.BeginUpdate;
  try
    // 确保富文本编辑框足够大,以容纳插入的代码
    ARichEdit.MaxLength := ARichEdit.MaxLength + AStream.Size;
    // 通过EM_STREAMIN消息将RTF流式传输
    EditStream.dwCookie := DWORD_PTR(AStream);
    EditStream.dwError := 0;
    EditStream.pfnCallback := @EditStreamReader;
    ARichEdit.Perform(
      EM_STREAMIN,
      SFF_SELECTION or SF_RTF or SFF_PLAINRTF,
      LPARAM(@EditStream)
    );
    // 报告任何错误作为错误
    if EditStream.dwError <> 0 then
      raise Exception.Create('RTFInsertStream: 插入流时出错');
  finally
    ARichEdit.Lines.EndUpdate;
  end;
end;
英文:

Your TEditStreamCallBack and EditStreamReader declarations do not match.

Also, you are handling the cookie as a 32bit integer in both 32bit and 64bit builds, which is wrong. It needs to be a 32bit integer in a 32bit build, and a 64bit integer in a 64bit build. The Win32 API declares the cookie as a DWORD_PTR for exactly that purpose.

TEditStreamCallBack and TEditStream are already declared in the Winapi.RichEdit unit, you do not need to declare them manually in your own code.

Try this instead:

uses
  Winapi.RichEdit, SysUtils;

function EditStreamReader(dwCookie: DWORD_PTR; pbBuff: PByte; cb: Longint; var pcb: Longint): Longint; stdcall;
begin
  Result := 0;  // assume no error
  try
    pcb := TStream(dwCookie).Read(pBuff^, cb); // read data from stream
  except
    Result := -1;  // indicates error to calling routine
  end;
end;

class procedure TpRichEditUtils.RTFInsertStream(const ARichEdit : TRichEdit; const AStream: TStream);
var
  EditStream: TEditStream;  // callback used to read inserted RTF
begin
  ARichEdit.Lines.BeginUpdate;
  try
    // Make sure rich edit is large enough to take inserted code
    ARichEdit.MaxLength := ARichEdit.MaxLength + AStream.Size;
    // Stream in the RTF via EM_STREAMIN message
    EditStream.dwCookie := DWORD_PTR(AStream);
    EditStream.dwError := 0;
    EditStream.pfnCallback := @EditStreamReader;
    ARichEdit.Perform(
      EM_STREAMIN,
      SFF_SELECTION or SF_RTF or SFF_PLAINRTF,
      LPARAM(@EditStream)
    );
    // Report any errors as a bug
    if EditStream.dwError &lt;&gt; 0 then
      raise Exception.Create(&#39;RTFInsertStream: Error inserting stream&#39;);
  finally
    ARichEdit.Lines.EndUpdate;
  end;
end;

huangapple
  • 本文由 发表于 2023年6月6日 00:39:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76408432.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定