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

Delphi 64位环境下RTF流插入RichEdit控件失败求助

解决Delphi 10.4 64位下RichEdit插入RTF流的访问违例问题

问题根源是自定义的TEditStream结构和回调函数参数类型与64位Windows API定义不匹配:32位环境下指针和Longint都是4字节,不会截断;但64位下指针是8字节,用4字节类型存储会导致指针截断,触发访问违例。以下是修正后的完整代码:

修正后的代码

type
  // 严格匹配Windows API的EDITSTREAMCALLBACK定义,64位下dwCookie为指针大小
  TEditStreamCallBack = function(dwCookie: DWORD_PTR; pbBuff: PByte;  
    cb: DWORD; var pcb: DWORD): DWORD; stdcall;

  // 对齐Windows原生EDITSTREAM结构
  TEditStream = record
    dwCookie: DWORD_PTR;
    dwError: DWORD;
    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_PTR; pbBuff: PByte; cb: DWORD; var pcb: DWORD): DWORD; stdcall;
begin
  Result := 0;  // 默认无错误
  try
    // 64位下DWORD_PTR可完整存储TStream指针,避免截断
    pcb := TStream(dwCookie).Read(pbBuff^, cb);
  except
    Result := $FFFF;  // 向调用方报告错误
  end;
end;

class procedure TpRichEditUtils.RTFInsertStream(const ARichEdit : TRichEdit; const AStream: TStream);
var
  EditStream: TEditStream;
  StreamPos: Int64;
begin
  ARichEdit.Lines.BeginUpdate;
  try
    // 保存流当前位置,操作完成后恢复
    StreamPos := AStream.Position;
    AStream.Position := 0;

    // 调整RichEdit最大长度以容纳插入内容
    ARichEdit.MaxLength := ARichEdit.MaxLength + AStream.Size;

    // 初始化流回调结构
    EditStream.dwCookie := DWORD_PTR(AStream);
    EditStream.dwError := 0;
    EditStream.pfnCallback := @EditStreamReader;

    // 发送EM_STREAMIN消息,将RTF插入选中位置
    ARichEdit.Perform(
      EM_STREAMIN,
      SFF_SELECTION or SF_RTF or SFF_PLAINRTF,
      LPARAM(@EditStream)
    );

    if EditStream.dwError <> 0 then
      raise Exception.CreateFmt('插入RTF流出错,错误码: %d', [EditStream.dwError]);
  finally
    AStream.Position := StreamPos;
    ARichEdit.Lines.EndUpdate;
  end;
end;

// 调用示例
var
  OStream: TStringStream;
begin
  OStream := TStringStream.Create(ODmRemarqueStandard.REMSTD_TEXTE);
  try
    TpRichEditUtils.RTFInsertStream(TcxRichInnerEdit(EdtConditionGenerale.InnerControl), OStream);
  finally
    FreeAndNil(OStream)
  end;
end;

核心修改说明

  • 类型对齐:将TEditStream的dwCookie改为DWORD_PTR(64位下占8字节,可完整存储指针),dwError改为DWORD,与Windows原生结构完全一致。
  • 回调参数修正:回调函数的cb、pcb参数改为DWORD,dwCookie改为DWORD_PTR,彻底避免类型转换时的指针截断。
  • 流状态保护:新增保存/恢复流位置的逻辑,防止操作后流位置被修改影响后续使用。
  • 错误信息优化:通过格式化输出错误码,便于问题排查。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 15:12:43