首页  编辑  

Richedit的扩展

Tags: /超级猛料/VCL/Memo&Edit&Richedit/RichEdit、RxRichEdit/   Date Created:

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将你的文本格式转化为二进制格式再存盘,否则直接存盘。