Hàm sau lấy văn bản đã chọn trong điều khiển Richedit
, ghi vào một hàm TMemoryStream
bên trong hàm gọi lại và sau đó trả về dưới dạng chuỗi văn bản thuần túy mã rtf thô.Tại sao mã này không thành công khi khai báo TMemoryStream cục bộ nhưng hoạt động khi được khai báo trên toàn cầu?
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;
Các công trình trên không như bất kỳ lỗi nào.
Tuy nhiên, tôi cố gắng tránh các biến được khai báo trên toàn cầu khi có thể và giữ chúng ở địa phương theo quy trình hoặc chức năng cần, nhưng vì lý do nào đó khai báo MS: TMemoryStream;
bên trong chức năng GetSelectedRTFCode
không thành công với lỗi Vi phạm hướng dẫn và truy cập.
Vì vậy, với ý nghĩ đó, và sự thay đổi duy nhất dưới đây được MS: TMemoryStream;
tuyên bố tại địa phương thất bại:
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;
Tại sao tuyên bố dòng biến bộ nhớ làm việc trên toàn cầu, nhưng thất bại khi tuyên bố tại địa phương?
Chỉ là System.Math cần thiết cho IfThen. Tôi đã không đề cập đến nó bởi vì tôi nghi ngờ bạn sẽ biết nơi để tìm thấy nó. Có thể được thực hiện với một câu lệnh if. –
Bạn cũng có thể ['thêm một số đường'] (http://pastebin.com/udGkgwUz). Btw. có vẻ như EMBT đang tiến gần hơn đến nguyên mẫu chính xác của cuộc gọi lại đó (chưa chính xác, nhưng gần hơn). Nó thay đổi kể từ Delphi XE3. Có lẽ trong XE8 sẽ được chính xác cuối cùng. – TLama
@TLama Ah, niềm vui của các nguyên mẫu Win32 được dịch sai. Trong trường hợp này, nó không quan trọng lắm bởi vì nó là 0, hay không 0. –