完成此程序(DELPHI 2010):
procedure TfrmMainApp.ChangeLogon;
var
EncStr: TEncodedStream; // from M.Cantu, see below
LogonName : tUserName;
LogonPW : tPassword;
MessageString: string;
begin
if MessageDlg('You are about to change the login to the Connection server. Do you wish to continue?',
mtWarning, [mbYes, mbNo], 0) = mrYes then
begin
LogonName := '';
LogonPW := '';
with dlgPWLogIn do
begin
Caption := 'Change Database Logon';
edtPassword.CharCase := ecNormal;
gbPrompt.Caption := 'Enter User name:';
edtPassword.PasswordChar := #0;
end;
if dlgPWLogIn.ShowModal = mrOK then
begin
LogonName := dlgPWLogIn.edtPassword.Text;
dlgPWLogIn.Release;
Application.CreateForm(TdlgPWLogIn, dlgPWLogIn);
with dlgPWLogIn do
begin
Caption := 'Change Logon';
edtPassword.CharCase := ecNormal;
gbPrompt.Caption := 'Enter Password:';
edtPassword.PasswordChar := cPASSWORD_CHAR;
end;
if dlgPWLogIn.ShowModal = mrOK then
begin
LogonPW := dlgPWLogIn.edtPassword.Text;
FLogParams.Clear;
FLogParams.Add(trim(LogonName));
FLogParams.Add(trim(LogonPW));
//* send and save above params to logon txt file
EncStr := TEncodedStream.Create('dblogon.txt', fmCreate);
try
FLogParams.SaveToStream (EncStr);
// ...
// ...
// ... anything executed here is in error!
finally
begin
EncStr.Free;
end;
end;
end
else
MessageDlg('Cancelled By User.', mtInformation, [mbOK], 0);
end
else
MessageDlg('Cancelled By User.', mtInformation, [mbOK], 0);
end
else
MessageDlg('Cancelled By User.', mtInformation, [mbOK], 0);
end;
问题:在FLogParams.SaveToStream(EncStr)行之后执行的任何操作(例如信息信息)或执行过程后出现错误::我在EXE上收到ACCESS VIOLATION错误。
我已经测试了相同的TEncodedStream类,其中包含要从Tmemo保存的文本,并且它工作正常,所以我来客的故障是在用于保存临时文本的TStringList中(FLogParams是先前创建并发布的TStringList)形式被破坏了。)
寻求帮助。
注意:TEncodedStream类是由M.Cantu编写的。它是以下内容:
unit EncodStr;
Interface
uses
Classes;
type
TEncodedStream = class (TFileStream)
private
FKey: Char;
public
constructor Create(const FileName: string; Mode: Word);
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
property Key: Char read FKey write FKey default 'A';
end;
implementation
constructor TEncodedStream.Create(
const FileName: string; Mode: Word);
begin
inherited Create (FileName, Mode);
FKey := 'A';
end;
function TEncodedStream.Write(const Buffer;
Count: Longint): Longint;
var
pBuf, pEnc: PChar;
I, EncVal: Integer;
begin
// allocate memory for the encoded buffer
GetMem (pEnc, Count);
try
// use the buffer as an array of characters
pBuf := PChar (@Buffer);
// for every character of the buffer
for I := 0 to Count - 1 do
begin
// encode the value and store it
EncVal := ( Ord (pBuf[I]) + Ord(Key) ) mod 256;
pEnc [I] := Chr (EncVal);
end;
// write the encoded buffer to the file
Result := inherited Write (pEnc^, Count);
finally
FreeMem (pEnc, Count);
end;
end;
function TEncodedStream.Read(var Buffer; Count: Longint): Longint;
var
pBuf, pEnc: PChar;
I, CountRead, EncVal: Integer;
begin
// allocate memory for the encoded buffer
GetMem (pEnc, Count);
try
// read the encoded buffer from the file
CountRead := inherited Read (pEnc^, Count);
// use the output buffer as a string
pBuf := PChar (@Buffer);
// for every character actually read
for I := 0 to CountRead - 1 do
begin
// decode the value and store it
EncVal := ( Ord (pEnc[I]) - Ord(Key) ) mod 256;
pBuf [I] := Chr (EncVal);
end;
finally
FreeMem (pEnc, Count);
end;
// return the number of characters read
Result := CountRead;
end;
end.
---------
Exemple of using this class given by M CAntu:
unit EncForm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TFormEncode = class(TForm)
Memo1: TMemo;
Memo2: TMemo;
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
Panel1: TPanel;
BtnLoadPlain: TButton;
BtnSaveEncoded: TButton;
BtnLoadEncoded: TButton;
Splitter1: TSplitter;
procedure BtnSaveEncodedClick(Sender: TObject);
procedure BtnLoadEncodedClick(Sender: TObject);
procedure BtnLoadPlainClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
FormEncode: TFormEncode;
implementation
{$R *.DFM}
uses
EncodStr;
procedure TFormEncode.BtnSaveEncodedClick(Sender: TObject);
var
EncStr: TEncodedStream;
begin
if SaveDialog1.Execute then
begin
EncStr := TEncodedStream.Create(SaveDialog1.Filename, fmCreate);
try
Memo1.Lines.SaveToStream (EncStr);
finally
EncStr.Free;
end;
end;
end;
procedure TFormEncode.BtnLoadEncodedClick(Sender: TObject);
var
EncStr: TEncodedStream;
begin
if OpenDialog1.Execute then
begin
EncStr := TEncodedStream.Create(OpenDialog1.FileName, fmOpenRead);
try
Memo2.Lines.LoadFromStream (EncStr);
finally
EncStr.Free;
end;
end;
end;
procedure TFormEncode.BtnLoadPlainClick(Sender: TObject);
begin
if OpenDialog1.Execute then
Memo1.Lines.LoadFromFile (
OpenDialog1.FileName);
end;
end.
=============================
EDITED:
Thanks: Ansifying the TEncodedStream corrected the problem:
unit EncodStr;
interface
uses
Classes;
type
TEncodedStream = class (TFileStream)
private
FKey: ansiChar;
public
constructor Create(const FileName: string; Mode: Word);
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
property Key: ansiChar read FKey write FKey default 'A';
end;
implementation
constructor TEncodedStream.Create(
const FileName: string; Mode: Word);
begin
inherited Create (FileName, Mode);
FKey := 'A';
end;
function TEncodedStream.Write(const Buffer;
Count: Longint): Longint;
var
pBuf, pEnc: PansiChar;
I, EncVal: Integer;
begin
// allocate memory for the encoded buffer
GetMem (pEnc, Count);
try
// use the buffer as an array of characters
pBuf := PansiChar (@Buffer);
// for every character of the buffer
for I := 0 to Count - 1 do
begin
// encode the value and store it
EncVal := ( Ord (pBuf[I]) + Ord(Key) ) mod 256;
pEnc [I] := AnsiChar (EncVal);
end;
// write the encoded buffer to the file
Result := inherited Write (pEnc^, Count);
finally
FreeMem (pEnc, Count);
end;
end;
function TEncodedStream.Read(var Buffer; Count: Longint): Longint;
var
pBuf, pEnc: PansiChar;
I, CountRead, EncVal: Integer;
begin
// allocate memory for the encoded buffer
GetMem (pEnc, Count);
try
// read the encoded buffer from the file
CountRead := inherited Read (pEnc^, Count);
// use the output buffer as a string
pBuf := PansiChar (@Buffer);
// for every character actually read
for I := 0 to CountRead - 1 do
begin
// decode the value and store it
EncVal := ( Ord (pEnc[I]) - Ord(Key) ) mod 256;
pBuf [I] := ansiChar (EncVal);
end;
finally
FreeMem (pEnc, Count);
end;
// return the number of characters read
Result := CountRead;
end;
end.
答案 0 :(得分:3)
我没有附近的Windows PC来测试它,但是猜测,你在Delphi 2010上击中Char是一个多字节的项目,而TEncodeStream类的代码假设Char是一个单字节项。您应该将TEncodeStream类中的代码转换为显式使用AnsiString / AnsiChar