英文:
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 <> $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.
答案1
得分: 1
Your TEditStreamCallBack
和 EditStreamReader
声明不匹配。
此外,在32位和64位版本中都将cookie处理为32位整数是错误的。在32位版本中,它需要是32位整数,在64位版本中,它需要是64位整数。Win32 API声明cookie为 DWORD_PTR
就是为了这个目的。
TEditStreamCallBack
和 TEditStream
已经在 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 <> 0 then
raise Exception.Create('RTFInsertStream: Error inserting stream');
finally
ARichEdit.Lines.EndUpdate;
end;
end;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论