Richedit的扩展
lpa(lpa)
我通过Richedit.RegisterConversionFormat(const AExtension: string; AConversionClass: TConversionClass);方法注册了若干种格式的二进制文件,
每种格式(AConversionClass1、AConversionClass2、。。。)都重载了
ConvertReadstream、ConvertWritestream函数,这样就可以通过Richedit.Lines.LoadFromFile来实现对这些文件的编辑了。问题是,假如我打开了第一种格式的文件(这时Richedit.Lines.LoadFromFile时调用的是AConversionClass1的ConvertReadstream函数),再打开第二种格式的文件,这时Richedit.Lines.LoadFromFile时调用的就应该是AConversionClass2的ConvertReadstream函数了,但实际上还是调用AConversionClass1的ConvertReadstream函数,而不管先打开的文件有没有存盘(Richedit.Lines.SaveToFile)。需要声明:第一次打开文件时,不管是哪种格式(已经注册过的几种之一),都能正确地按照我重载的ConvertReadstream那样以文本形式显示该种格式文件。打开另一个文件时,只要格式与第一次打开的文件格式相同,也没有问题。但是格式不同就会出错。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls;
type
Teq2 = record
EQYear: smallint;
EQMonth, EQDay: Byte;
EQHour, EQMinute: Byte;
EQLatitude: smallint;
EQLongtitude: smallint;
Ms, EQSecond: Byte;
EQDepth: smallint;
EQSerial: smallint;
end; // 以上是你的二进制格式文件的格式,并且这些文件都有扩展名*.eq2
type
TEQ2Conversion = class(TConversion)
public
function ConvertReadStream(Stream: TStream; Buffer: PChar;
BufSize: integer): integer; override;
function ConvertWriteStream(Stream: TStream; Buffer: PChar;
BufSize: integer): integer; override;
end;
type
TForm1 = class(TForm)
RichEdit1: TRichEdit;
Button1: TButton;
OpenDialog1: TOpenDialog;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function TEQ2Conversion.ConvertReadStream(Stream: TStream; Buffer: PChar; BufSize: integer): integer;
var s: string;
buf: array[1..16] of char;
n: integer;
begin
Result := 0;
if BufSize = 0 then Exit;
s := '';
n := Stream.Read(buf, 16);
if n = 0 then Exit;
if ((Ord(buf[2])) shr 7) = 1 then
AppendStr(s, StringOfChar(' ', 4 - length(IntToStr(((ord(buf[2])) shl 8) + ord(buf[1]) - 65536))) + IntToStr(((ord(buf[2])) shl 8) + ord(buf[1]) - 65536) + ',')
else
AppendStr(s, StringOfChar(' ', 4 - length(IntToStr(((ord(buf[2])) shl 8) + ord(buf[1])))) + IntToStr(((ord(buf[2])) shl 8) + ord(buf[1])) + ',');
//((ord(buf[2])) SHL 8)+ord(buf[1]))为年的值:第二个字节的值乘以256加上第一个字节的值
if length(IntToStr(ord(buf[3]))) = 2 then
AppendStr(s, IntToStr(ord(buf[3])) + ',')
else AppendStr(s, '0' + IntToStr(ord(buf[3])) + ',');
//ord(buf[3])为月的值:第三个字节的值
if length(IntToStr(ord(buf[4]))) = 2 then
AppendStr(s, IntToStr(ord(buf[4])) + ',')
else AppendStr(s, '0' + IntToStr(ord(buf[4])) + ',');
//ord(buf[4])为日的值:第四个字节的值
if Length(IntToStr(ord(buf[5]))) = 2 then AppendStr(s, IntToStr(ord(buf[5])) + ',')
else AppendStr(s, '0' + IntToStr(ord(buf[5])) + ',');
//ord(buf[5])为时的值:第五个字节的值
if length(IntToStr(ord(buf[6]))) = 2 then
AppendStr(s, IntToStr(ord(buf[6])) + ',')
else AppendStr(s, '0' + IntToStr(ord(buf[6])) + ',');
//ord(buf[6])为分的值:第六个字节的值
if length(IntToStr(ord(buf[12]))) = 2 then
AppendStr(s, IntToStr(ord(buf[12])) + ',')
else AppendStr(s, '0' + IntToStr(ord(buf[12])) + ',');
//ord(buf[12])为秒的值:第十二个字节的值
AppendStr(s, StringOfChar(' ', 7 - length(FloatToStr((((ord(buf[10])) shl 8) + (ord(buf[9]))) / 100))) + FloatToStr((((ord(buf[10])) shl 8) + (ord(buf[9]))) / 100) + ',');
//(((ord(buf[10])) SHL 8)+ord(buf[9]))/100为经度的值:第十个字节的值乘以256加上第九个字节的值
AppendStr(s, StringOfChar(' ', 6 - length(FloatToStr((((ord(buf[8])) shl 8) + ord(buf[7])) / 100))) + FloatToStr((((ord(buf[8])) shl 8) + (ord(buf[7]))) / 100) + ',');
//(((ord(buf[8])) SHL 8)+ord(buf[7]))/100为纬度的值:第八个字节的值乘以256加上第七个字节的值
AppendStr(s, StringOfChar(' ', 3 - length(FloatToStr((ord(buf[11])) / 10))) + FloatToStr((ord(buf[11])) / 10) + ',');
//(ord(buf[11]))/10为震级的值:第十一个字节的值除以10
if (((ord(buf[14])) shl 8) + ord(buf[13])) > 999 then AppendStr(s, '---,')
else
AppendStr(s, StringOfChar(' ', 3 - length(IntToStr(((ord(buf[14])) shl 8) + ord(buf[13])))) + IntToStr(((ord(buf[14])) shl 8) + ord(buf[13])) + ',');
//((ord(buf[14])) SHL 8)+ord(buf[13]))为深度的值:第十四个字节的值乘以256加上第十三个字节的值
AppendStr(s, StringOfChar(' ', 3 - length(IntToStr(((ord(buf[16])) shl 8) + ord(buf[15])))) + IntToStr(((ord(buf[16])) shl 8) + ord(buf[15])));
//((ord(buf[16])) SHL 8)+ord(buf[15]))为序列号的值:第十六个字节的值乘以256加上第十五个字节的值
AppendStr(s, #13#10);
StrPCopy(Buffer, s);
Result := length(s);
end;
const TwoPower8 = 256;
function TEQ2Conversion.ConvertWriteStream(Stream: TStream; Buffer: PChar;
BufSize: integer): integer;
var s: string;
n, code: integer;
EQ2Rec: TEQ2;
begin
Result := 0;
if BufSize = 0 then Exit;
s := '';
with EQ2Rec do
begin
SetLength(s, 4);
for n := 1 to 4 do s[n] := buffer[n - 1];
Val(s, EQYear, code);
SetLength(s, 2);
for n := 1 to 2 do s[n] := buffer[n + 4];
Val(s, EQMonth, code);
for n := 1 to 2 do s[n] := buffer[n + 7];
Val(s, EQDay, code);
for n := 1 to 2 do s[n] := buffer[n + 10];
Val(s, EQHour, code);
for n := 1 to 2 do s[n] := buffer[n + 13];
Val(s, EQMinute, code);
SetLength(s, 2);
for n := 1 to 2 do s[n] := buffer[n + 16];
Val(s, EQSecond, code);
SetLength(s, 7);
for n := 1 to 7 do s[n] := buffer[n + 19];
case pos('.', s) of
0:
begin
Val(s, EQLongtitude, code);
EQLongtitude := EQLongtitude * 100;
end;
6:
begin
delete(s, 6, 1);
Val(s, EQLongtitude, code);
EQLongtitude := EQLongtitude * 10;
end;
5:
begin
n := 7;
if s[n] = ' ' then s[n] := '0';
delete(s, 5, 1);
Val(s, EQLongtitude, code);
end;
else
begin
delete(s, pos('.', s) + 3, 7 - pos('.', s) - 2);
if s[pos('.', s) + 2] = ' ' then s[pos('.', s) + 2] := '0';
delete(s, pos('.', s), 1);
Val(s, EQLongtitude, code);
end;
end;
SetLength(s, 6);
for n := 1 to 6 do s[n] := buffer[n + 27];
case pos('.', s) of
0:
begin
Val(s, EQLatitude, code);
EQLatitude := EQLatitude * 100;
end;
5:
begin
delete(s, 5, 1);
Val(s, EQLatitude, code);
EQLatitude := EQLatitude * 10;
end;
4:
begin
n := 6;
if s[n] = ' ' then s[n] := '0';
delete(s, 4, 1);
Val(s, EQLatitude, code);
end
else
begin
delete(s, pos('.', s) + 3, 6 - pos('.', s) - 2);
if s[pos('.', s) + 2] = ' ' then s[pos('.', s) + 2] := '0';
delete(s, pos('.', s), 1);
Val(s, EQLatitude, code);
end;
end;
SetLength(s, 3);
for n := 1 to 3 do s[n] := buffer[n + 34];
case pos('.', s) of
0:
begin
Val(s, Ms, code);
Ms := Ms * 10;
end;
1:
begin
delete(s, 3, 1);
delete(s, 1, 1);
Val(s, Ms, code);
end;
2:
begin
delete(s, 2, 1);
Val(s, Ms, code);
end;
end;
SetLength(s, 3);
for n := 1 to 3 do s[n] := buffer[n + 38];
Val(s, EQDepth, code);
for n := 1 to 3 do s[n] := buffer[n + 42];
Val(s, EQSerial, code);
SetLength(s, 48);
s := '';
AppendStr(s, chr(Byte(EQYear and (TwoPower8 - 1))));
AppendStr(s, chr(Byte(EQYear shr 8)));
AppendStr(s, chr(EQMonth));
AppendStr(s, chr(EQDay));
AppendStr(s, chr(EQHour));
AppendStr(s, chr(EQMinute));
AppendStr(s, chr(Byte(EQLatitude and (TwoPower8 - 1))));
AppendStr(s, chr(Byte(EQLatitude shr 8)));
AppendStr(s, chr(Byte(EQLongtitude and (TwoPower8 - 1))));
AppendStr(s, chr(Byte(EQLongtitude shr 8)));
AppendStr(s, chr(Ms));
AppendStr(s, chr(EQSecond));
AppendStr(s, chr(Byte(EQDepth and (TwoPower8 - 1))));
AppendStr(s, chr(Byte(EQDepth shr 8)));
AppendStr(s, chr(Byte(EQSerial and (TwoPower8 - 1))));
AppendStr(s, chr(Byte(EQSerial shr 8)));
end;
n := Stream.Write(PChar(s)^, length(s));
if n = 0 then exit;
Result := 48;
end;
procedure TForm1.FormCreate(Sender: TObject);
var Current_Language: TLanguages;
begin
OpenDialog1.InitialDir := Application.ExeName;
//下面一句注册你的文件格式
Richedit1.RegisterConversionFormat('EQ2', TEQ2Conversion);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if OpenDialog1.Execute then
begin
if FileExists(OpenDialog1.FileName) then
begin
Caption := OpenDialog1.FileName;
RichEdit1.Lines.LoadFromFile(OpenDialog1.FileName);
end
else ShowMessage('文件:' + OpenDialog1.FileName + '未找到!');
RichEdit1.Modified := False;
end;
RichEdit1.SetFocus;
end;
end.
如果你打开*.eq2文件,就会调用TEQ2Converssion的ConvertReadStream将二进制格式转化为你希望的文本格式显示在Richedit1,否则就默认为文本文件直接将文件内容显示在Richedit1;同理,RichEdit1.SaveToFile时也会根据文件名来处理,如果扩展名为*.eq2则先调用TEQ2Converssion的ConvertWriteStream将你的文本格式转化为二进制格式再存盘,否则直接存盘。