在Delphi中反序列化时显示表单中的访问冲突

时间:2012-12-15 13:30:47

标签: delphi delphi-xe2

我通过序列化和表单及其内容的反序列化编写了以下代码到Delphi

unit SerAndDeser;

interface

  uses Classes,MainForm,ListOfTables,DataOfTable,SerialForms,sysutils,ActiveX, DatabaseClasses, UnloadProcs;

  procedure Ser();
  procedure Deser();
  function GetGUID(): string;
  function DeleteSymbols(inputstr : string) : string;
implementation

  function GetGUID(): string;
  var
  GUID : TGUID;
  begin
  Result := '';
  if CoCreateGuid(GUID) = 0 then
    Result := GUIDToString(GUID);
    Result := StringReplace(Result, '{', '', []);
    Result := StringReplace(Result, '}', '', []);
    Result := StringReplace(Result, '-', '', [rfReplaceAll]);
  end;

  function DeleteSymbols(inputstr : string): string;
  begin
  Result := '';
    Result := StringReplace(inputstr, '-', '', [rfReplaceAll]);
    Result := StringReplace(Result, ' ', '', [rfReplaceAll]);
    Result := StringReplace(Result, '\', '', [rfReplaceAll]);
    Result := StringReplace(Result, '/', '', [rfReplaceAll]);
  end;

  procedure Ser();

    var mForm : MainFormInfo;
        tForm : TableFormInfo;
        lForm : ListFormInfo;
        tempFmtable : TfmTableData;
        i,j : integer;
        MyFileStream : TFileStream;
        MyMemoryStream : TMemoryStream;
        field : TableFieldInfo;
  begin
        try
      mForm := nil;

      mForm := MainFormInfo.Create(
        nil,
        MainWindow.Left,
        MainWindow.Top,
        MainWindow.Height,
        MainWindow.Width,
        MainWindow.partofconnectstring,
        MainWindow.dbname,
        MainWindow.dbfilename);
      mForm.Name := 'MainWindow';

      //table forms
      try
        tForm := nil;
        field := nil;

        for i := 0 to MainWindow.ComponentCount - 1 do
          if (MainWindow.Components[i] is TfmTableData) then
            begin
              tempFmtable := MainWindow.Components[i] as TfmTableData;
              tForm := TableFormInfo.Create(
                mForm,
                tempFmtable.Left,
                tempFmtable.Top,
                tempFmtable.Height,
                tempFmtable.Width,
                tempFmtable.tname);
              tForm.Name := tempFmtable.Name;

              //fields
              for j := 0 to tempFmtable.DBGrid1.Columns.Count - 1 do
              begin
                field := nil;

                field := TableFieldInfo.Create(
                  tForm,
                  tempFmtable.DBGrid1.Columns[j].FieldName,
                  tempFmtable.DBGrid1.Columns[j].Title.Caption,
                  tempFmtable.DBGrid1.Columns[j].Index,
                  tempFmtable.DBGrid1.Columns[j].Visible);
                  field.Name := DeleteSymbols(tempFmtable.DBGrid1.Columns[j].FieldName);{tempFmtable.DBGrid1.Columns[j].FieldName} {+ GetGUID;}
              end;
              //

            end;
      except
        field.Free;
        tForm.Free;
      end;
      //

      //List form
      try
        lForm := nil;
        lForm := ListFormInfo.Create(
          mForm,
          fmListOfTables.Left,
          fmListOfTables.Top,
          fmListOfTables.Height,
          fmListOfTables.Width);
        lForm.Name := 'fmListOfTables';
      except
        lForm.Free;
      end;
      //

      //save
      MyFileStream := nil;
      MyMemoryStream := nil;

      MyFileStream := TFileStream.Create('test.txt', fmCreate);
      MyMemoryStream := TMemoryStream.Create;
      MyMemoryStream.WriteComponent(mForm);
      MyMemoryStream.Position := 0;
      ObjectBinaryToText(MyMemoryStream,MyFileStream);
      MainWindow.Panel1.DockManager.SaveToStream(MyFileStream);
      //

    finally
      mForm.Free;
      MyFileStream.Free;
      MyMemoryStream.Free;
    end;
  end;


  procedure Deser();

    var mForm : MainFormInfo;
        tForm : TableFormInfo;
        lForm : ListFormInfo;
        tempFmtable : TfmTableData;
        i,j : integer;
        MyFileStream : TFileStream;
        MyMemoryStream : TMemoryStream;
        table : TTableSpec;
        descr : string;
        field : TableFieldInfo;


  begin
    try
      //destroy environment
      i := 0;
      while (i <= MainWindow.ComponentCount - 1) do
      begin
        if MainWindow.Components[i] is TfmTableData then
          try
            tempFmTable := nil;
            tempFmTable := MainWindow.Components[i] as TfmTableData;
            tempFmTable.IBQuery1.Close;
            tempFmtable.Free;
          except
            tempFmTable.Free;
          end
        else
          inc(i);
      end;
      fmListOfTables.Free;
      DBSchema.Free;
      //

      //read
      mForm := nil;
      MyFileStream := nil;
      MyMemoryStream := nil;

      mForm := MainFormInfo.Create(nil, -1, -1, -1, -1, MainWindow.partofconnectstring, MainWindow.dbname, MainWindow.dbfilename);

      MyFileStream := TFileStream.Create('test.txt', fmOpenRead);
      MyMemoryStream := TMemoryStream.Create;
      ObjectTextToBinary(MyFileStream,MyMemoryStream);
      MyMemoryStream.Position := 0;
      MyMemoryStream.ReadComponent(mForm);
      //

      //go
      UnloadProcs.ConnectToDatabase(MainWindow.partofconnectstring, MainWindow.SQLConnection1);
      //UnloadProcs.CreateObjs(MainWindow.SQLConnection1, MainForm.DBSchema);
      //fmListOfTables.Show;

      MainWindow.Left := mForm.LeftValue;
      MainWindow.Top := mForm.TopValue;
      MainWindow.Height := mForm.HeightValue;
      MainWindow.Width := mForm.WidthValue;

      //list
      i := 0;
      while i <= mForm.ComponentCount - 1 do
      begin
        if mForm.Components[i] is ListFormInfo then
          try
            lForm := nil;
            lForm := mForm.Components[i] as ListFormInfo;
            fmListOfTables.Left := lForm.LeftValue;
            fmListOfTables.Top := lForm.TopValue;
            fmListOfTables.Height := lForm.HeightValue;
            fmListOfTables.Width := lForm.WidthValue;
            fmListOfTables.Show;
            inc(i);
          finally
            lForm.Free;
          end
        else
          inc(i);
      end;
      //

      //fmListOfTables.Show;
      //tables
      for j := 0 to mForm.ComponentCount - 1 do
        if mForm.Components[j] is TableFormInfo then
          try
            table := nil;
            tempFmtable := nil;
            tForm := nil;

            tForm := mForm.Components[j] as TableFormInfo;

            table := TTableSpec(DBSchema.Tables.FindComponent(tForm.Table));
            tempFmtable := TfmTableData.Create(MainWindow);
            tempFmtable.Name := tForm.Name;
            tempFmtable.tname := tForm.Table;
            //tempFmtable.Caption := Utf8ToAnsi(table.Description);
            tempFmtable.Left := tForm.LeftValue;
            tempFmtable.Top := tForm.TopValue;
            tempFmtable.Height := tForm.HeightValue;
            tempFmtable.Width := tForm.WidthValue;

            tempFmtable.IBQuery1.SQL.Add('select * from ' + table.Name);
            tempFmtable.IBQuery1.Open;

            i := 0;
            while i <= tForm.ComponentCount - 1 do
              if tForm.Components[i] is TableFieldInfo then
              begin
                field := nil;

                field := tForm.Components[i] as TableFieldInfo;
                tempFmtable.DBGrid1.Columns[i].FieldName := field.FieldNameValue;
                tempFmtable.DBGrid1.Columns[i].Title.Caption := field.DescriptionValue;
                tempFmtable.DBGrid1.Columns[i].Index := field.IndexValue;
                tempFmtable.DBGrid1.Columns[i].Visible := field.VisibleValue;
                //tempFmtable.CheckListBox1.Items.Add(field.Description);
                //tempFmtable.CheckListBox1.Checked[i] := field.Visible;
                inc(i);
              end
              else
                inc(i);

            {for i := 0 to table.Fields.ComponentCount - 1 do
            begin
              descr := Utf8ToAnsi(((table.Fields.Components[i]) as TFieldSpec).Description);
              tempFmtable.CheckListBox1.Items.Add(descr);
              tempFmtable.DBGrid1.Columns[i].Title.Caption := descr;
              tempFmtable.CheckListBox1.Checked[i] := true;
            end; }

            tempFmtable.Show;


          except
            tempFmtable.Free;
            tForm.Free;
            table.Free;
          end;
      //

      //dock
      MainWindow.Panel1.DockManager.BeginUpdate;
      MainWindow.Panel1.DockManager.LoadFromStream(MyFileStream);
      MainWindow.Panel1.DockManager.ResetBounds(TRUE);
      MainWindow.Panel1.DockManager.EndUpdate;


      //
    finally
      MyFileStream.Free;
      MyMemoryStream.Free;
    end;

  end;

end.

调试时我发现在行

处发出“地址访问冲突”异常
fmListOfTables.Show;

在以下代码块中的代码更高

      i := 0;
      while i <= mForm.ComponentCount - 1 do
      begin
        if mForm.Components[i] is ListFormInfo then
          try
            lForm := nil;
            lForm := mForm.Components[i] as ListFormInfo;
            fmListOfTables.Left := lForm.LeftValue;
            fmListOfTables.Top := lForm.TopValue;
            fmListOfTables.Height := lForm.HeightValue;
            fmListOfTables.Width := lForm.WidthValue;
            fmListOfTables.Show;
            inc(i);
          finally
            lForm.Free;
          end
        else
          inc(i);
      end;

在异常原点之后,线条的移动线

function TCustomForm.IsFormSizeStored: Boolean;
begin
  Result := AutoScroll or (HorzScrollBar.Range <> 0) or (VertScrollBar.Range <> 0);
end;

来自Vcl.Forms中的模块。帮助消除错误。

1 个答案:

答案 0 :(得分:5)

你有这行代码:

fmListOfTables.Free;

接着是:

fmListOfTables.Left := lForm.LeftValue;
fmListOfTables.Top := lForm.TopValue;
fmListOfTables.Height := lForm.HeightValue;
fmListOfTables.Width := lForm.WidthValue;
fmListOfTables.Show;

在两者之间,您不会为fmListOfTables分配任何内容。

这意味着fmListOfTables没有引用有效对象。因此,您可能会遇到运行时错误。