|            
6.2.7 记录的删除、插入、排序  
    删除一条记录的基本思路是:获取当前记录的位置并把该位置后的记录逐个向前移动。 文件在最后一条记录前截断。  
    for i:=CurrentRec+1 to Count-1 do 
    begin 
    seek(MethodFile,i); 
    read(MethodFile,MethodRec); 
    seek(MethodFile,i-1); 
    Write(MethodFile,MethodRec); 
    end; 
    Truncate(MethodFile);  
     为避免误删除,在进行删除操作前弹出一个消息框进行确认。删除后要更新全局变量的值和显示内容:  
    Count := Count - 1; 
    ChangeGrid;  
     完整的程序如下:  
    procedure TRecFileForm.DeleteButtonClick(Sender: TObject); 
    var 
    Newfile: MethodFileType; 
    MethodRec: TMethod; 
    NewFileName: String; 
    i: Integer; 
    begin 
    if FileOpened = False then Exit; 
    CurrentRec := StringGrid1.Row-1; 
    if CurrentRec < 0="" then="" exit;="">
    if MessageDlg('Delete Current Record ?', mtConfirmation, 
    [mbYes, mbNo], 0) = idYes then 
    begin 
    HazAttr.text := ''; 
    for I := CurrentRec+1 to Count-1 do 
    begin 
    seek(MethodFile,i); 
    read(MethodFile,MethodRec); 
    seek(MethodFile,i-1); 
    Write(MethodFile,MethodRec); 
    end; 
    Truncate(MethodFile); 
    Count := Count-1; 
    ChangeGrid; 
    end; 
    end; 
    这里所显示的删除操作简单明了。但在程序开始设计时我却走了一条弯路,后来发现虽然这种方法用于记录的删除操作显得笨拙、可笑,但却恰恰是记录插入、排序的思想。 
    这种思想的核心是创建一个新文件保存更新后的内容。若新文件顺利创建,则删除原文件,否则恢复原来的文件。程序清单如下:  
    procedure TRecFileForm.DeleteButtonClick(Sender: TObject); 
    var 
    Newfile: MethodFileType; 
    MethodRec: TMethod; 
    NewFileName: String; 
    i: Integer; 
    begin 
    if FileOpened = False then Exit; 
    CurrentRec := StringGrid1.Row-1; 
    if CurrentRec < 0="" then="" exit;="">
    if MessageDlg('Delete Current Record ?', mtConfirmation, 
    [mbYes, mbNo], 0) = idYes then 
    begin 
    HazAttr.text := ''; 
    NewFileName := ChangeFileExt(FileName,'.sav'); 
    try 
    AssignFile(NewFile,FileName); 
    ReWrite(NewFile); 
    Except 
    On EInOutError do 
    begin 
    Rename(MethodFile,FileName); 
    Exit; 
    end; 
    end; 
    for i := 1 to Count do 
    if I <> CurrentRec+1 then 
    begin 
    MethodRec := GridToRec(i); 
    Write(NewFile,MethodRec); 
    end; 
    closeFile(MethodFile); 
    try 
    AssignFile(MethodFile,Filename); 
    Reset(MethodFile); 
    except 
    on EInOutError do 
    begin 
    DeleteFile(FileName); 
    AssignFile(MethodFile,NewFileName); 
    Reset(MethodFile); 
    Rename(MethodFile,FileName); 
    Exit; 
    end; 
    DeleteFile(NewFileName); 
    Count:=Count-1; 
    ChangeGrid; 
    end; 
    end; 
    对于记录插入,方法基本同上。对于排序,可先将关键域读入排序,而后再按排序结果对应的记录号顺序重写文件。  
    6.2.8 结果综合  
    对不同方法的评估结果,可按一定的公式进行综合。当用户按下“计算”按钮时,系统进行计算并把综合结果写入HazAttr只读编辑框中。 
    为保证结果显示的正确性,每次增加、修改、删除操作确认后HazAttr编辑框清空。  
    6.2.9 编辑对话框的输入检查  
    当用户单击“增加”或“修改”按钮时系统将弹出一个编辑对话框,让用户输入或修改记录内容。其中的三个编辑框,一个组合列表框分别对应TMethod 的四个域。由于TMethod的Result域必须是[0,1]间的小数,因此当用户按OK键关闭对话框时应进行类型和范围检查。 
    在VB中我做过同样的工作,那时需要对用户输入的键码逐个进行判断。但这种方法很繁琐、很难做圆满(如不能很好地支持编辑键)。而Object Pascal提供了更好的方法。这种方法的关键就在于它的类型转换函数Val:  
    procedure Val(Str: String;var V; var Code: Integer);  
    V是由Str转换成的整型或实型数。若字符串非法,则出错位置返至Code;否则置Code为0。字符串非法并不会引发一个转换异常。 
    如果转换后的数超出了我们的范围,则显式把Code置为-1。最后统一通过检测Code是否为0来判断输入是否合法。 
    我们把输入检查放在对话框的OnCloseQuery事件处理过程中。如输入非法,则禁止对话框关闭,并将输入焦点置于Result编辑框中。但假如用户按了Cancel按钮,则这种检查是多余的。为此定义一个布尔变量IsCancel,对话框生成时置为False。假如用户按下Cancel,则置为True,此时OnCloseQuery事件不进行输入检查。 
    对话框的OnCloseQuery事件处理过程的程序清单如下:  
    procedure TEditForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
    var 
    Res: Real; 
    k: Integer; 
    begin 
    if IsCancel = False then 
    begin 
    val(Result.text,Res,k); 
    if (Res > 1) or (Res < 0)="" then="" k="" :="-1;">
    if k <> 0 then 
    begin 
    MessageDlg('非法输入 !',mtWarning,[mbOK],0); 
    Result.text := ''; 
    CanClose := False; 
    Result.SetFocus; 
    end; 
    end; 
    end;        [1] [2] [3]  下一页  
 |