Следующая функция принимает выделенный текст в элементе управления Richedit
, записывает в TMemoryStream
внутри функции обратного вызова, а затем возвращает в виде строки обычного кода необработанный код rtf.
var
MS: TMemoryStream; // declared globally and works.
implementation
function GetSelectedRTFCode(RichEdit: TRichedit): string;
function RichEditCallBack(dwCookie: Longint; pbBuff: PByte;
CB: Longint; var pCB: Pointer): Longint; stdcall;
begin
MS.WriteBuffer(pbBuff^, CB);
Result := CB;
end;
var
EditStream: TEditStream;
SL: TStringList;
begin
MS := TMemoryStream.Create;
try
EditStream.dwCookie := SF_RTF or SFF_SELECTION;
EditStream.dwError := 0;
EditStream.pfnCallback := @RichEditCallBack;
Richedit.Perform(EM_StreamOut, SF_RTF or SFF_SELECTION, DWord(@EditStream));
MS.Seek(0, soBeginning);
SL := TStringList.Create;
try
SL.LoadFromStream(MS);
Result := SL.Text;
finally
SL.Free;
end;
finally
MS.Free;
end;
end;
Вышеуказанное работает как ожидалось без ошибок.
Тем не менее, я стараюсь избегать глобально объявленных переменных, когда это возможно, и сохранять их локальными в той процедуре или функции, которая им нужна, но по какой-то причине объявление MS: TMemoryStream;
внутри функции GetSelectedRTFCode
не выполняется с ошибками Priviliged Instruction и Access Violation.
Таким образом, имея в виду, и единственное изменение ниже MS: TMemoryStream;
, объявленное локально, не выполняется:
function GetSelectedRTFCode(RichEdit: TRichedit): string;
var
MS: TMemoryStream; // declare here instead of globally but fails.
function RichEditCallBack(dwCookie: Longint; pbBuff: PByte;
CB: Longint; var pCB: Pointer): Longint; stdcall;
begin
MS.WriteBuffer(pbBuff^, CB);
Result := CB;
end;
var
EditStream: TEditStream;
SL: TStringList;
begin
MS := TMemoryStream.Create;
try
EditStream.dwCookie := SF_RTF or SFF_SELECTION;
EditStream.dwError := 0;
EditStream.pfnCallback := @RichEditCallBack;
Richedit.Perform(EM_StreamOut, SF_RTF or SFF_SELECTION, DWord(@EditStream));
MS.Seek(0, soBeginning);
SL := TStringList.Create;
try
SL.LoadFromStream(MS);
Result := SL.Text;
finally
SL.Free;
end;
finally
MS.Free;
end;
end;
Почему объявить переменную потока памяти глобально, но не удается, если объявлено локально?