在RichEdit控件上放一个Image控件,用来显示图片 
现在想保存整个页面信息写入文件中,包括Image控件的位置信息以及图片信息,
(也就是控件本身的信息和图片的信息都要写到一个文件中) 
该如何做? 
(我的方法总是报错,可能是定义的文件结构有问题)
请教大家,谢谢!

解决方案 »

  1.   

    保存控件导文件和从文件中读取控件    
        
    saving several controls to one single file?{-> Question:How can I store some TRichEdit components and TEdit Components in a single file?-> Answer:Use a filestream and a reader or writer object.These ease the tasks of writing strings to a binary stream and reading them back.}// Save routineprocedure SaveEditcontrols(const FileName: string; const Controls: array of TCustomEdit);varfs : TFilestream;writer : TWriter;i : Integer;ss : TStringstream;beginfs := TFilestream.Create(FileName, fmCreate);trywriter := TWriter.Create(fs, 4096);tryfor i := Low(Controls) to High(Controls) doif Controls[i] is TCustomRichedit thenbeginss := TStringstream.Create(EmptyStr);trywith TRichedit(Controls[i]) dobeginPlaintext := False;Lines.SaveToStream(ss);end;writer.WriteString(ss.Datastring);finallyss.Free;end;endelsewriter.WriteString(Controls[i].Text);finallywriter.Free;end;finallyfs.Free;end;end;// Load routine// Lade Routineprocedure LoadEditcontrols(const FileName: string; const Controls: array of TCustomEdit);varfs : TFilestream;reader : Treader;i : Integer;ss : TStringstream;beginfs := TFilestream.Create(FileName, fmOpenread or fmShareDenyWrite);tryreader := Treader.Create(fs, 4096);tryfor i := Low(Controls) to High(Controls) doif Controls[i] is TCustomRichedit thenbeginss := TStringstream.Create(reader.ReadString);trywith TRichedit(Controls[i]) dobeginPlaintext := False;Lines.LoadfromStream(ss);end;finallyss.Free;end;endelseControls[i].Text := reader.ReadString;finallyreader.Free;end;finallyfs.Free;end;end;// Example to store 2 TRichEdits and 3 Edit Controls to one file// Beispiel, um 3 TRichEdits und 3 TEdit Controls in einer Datei zu speichernprocedure TForm1.Button1Click(Sender: TObject);beginSaveEditControls('C:\temp\temp.dat',[richedit1, richedit2, edit1, edit2, edit3]);end;
     
       
      

  2.   

    保存TWinControl上的组件到文件以及读入要点:用TStream类的WriteComponent和ReadComponent
    Example:
    //保存
    procedure SaveComponent(Con: TWinControl; Path: string);var
      BinStream:TMemoryStream;
    begin
      BinStream := TMemoryStream.Create;
      try
        BinStream.WriteComponent(Con);
        BinStream.Seek(0, soFromBeginning);
        BinStream.SaveToFile(Path);
      finally
        BinStream.Free
      end;
    end;
    //写回
    procedure ReadComponent(Path: string; Con: TWinControl);
    var
      BinStream: TMemoryStream;
      lp: integer;
      Com: TComponent;
    begin
      for lp := Con.ComponentCount - 1 downto 0 do
      begin
        Com := Con.Components[lp];
        Con.RemoveComponent(Com);
        Com.Free;
      end;
      BinStream := TMemoryStream.Create;
      try
        BinStream.LoadFromFile(Path);
        BinStream.ReadComponent(Con);
      finally
        BinStream.Free;
      end;
    end;
    //嘻嘻,简单吧!
    //Power by 海天子
      

  3.   

    按楼上的方法,不必通过内存流,直接操作文件流就行了.Example:
    //保存
    procedure SaveComponent(Con: TWinControl; Path: string);var
      Stream:TStream;
    begin
      Stream := TFileStream.Create(Path, fmCreate);
      try
        Stream.WriteComponent(Con);
      finally
        Stream.Free
      end;
    end;
    //写回
    procedure ReadComponent(Path: string; Con: TWinControl);
    var
      Stream: TStream;
      lp: integer;
      Com: TComponent;
    begin
      for lp := Con.ComponentCount - 1 downto 0 do
      begin
        Com := Con.Components[lp];
        Con.RemoveComponent(Com);
        Com.Free;
      end;
      Stream := TFileStream.Create(Path, fmOpenRead);
      try
        Stream.ReadComponent(Con);
      finally
        Stream.Free;
      end;
    end;//嘻嘻,简单多了!
      

  4.   

    继续请教楼上各位高手:
    我想保存的是TImage控件和其上的图片,写入一个文件
    我改写了上面的过程(我没有做过这方面,请指教!):
    procedure TMainForm.Savecontrols(const FileName:string;const Controls:array of TImage);
    var
      fs:TFilestream;
      writer:TWriter;
      i:Integer;
    begin
      fs:=TFilestream.Create(FileName,fmCreate);
      try
      writer:=TWriter.Create(fs,4096);
      try
      for i:=0 to 99 do
        with TImage(Controls[i]) do
        begin
          writer.WriteComponent(Controls[i]);//这里该怎么写?请教!
        end;
      finally
      writer.Free;
      end;
      finally
      fs.Free;
      end;
    end;
    我想把TImage控件和图片(TPicture)分别保存为两个控件数组,然后写入一个文件,
    这样可行吗?关键是打开文件时还应该能读出控件和图片,并在TImage上显示相应的图片
    有高手回答出这个问题,我给他另立散分贴,请教啦!!!
    万分感谢!!!
      

  5.   

    要写一个通用的读写元件流的函数很复杂,按你的要求可以写了一个简单的供参考。// 第一次运行时操作
    procedure TForm1.Button1Click(Sender: TObject);
    var
      S: TStream;
      Map: TImage;
      i: Integer;
    begin
    // 动态插入TImage元件到RichEdit,我插了3个,你可根据需要插入n个
      for i := 1 to 3 do
      begin
        Map := TImage.Create(Self);
        Map.Width := 100;
        Map.Height := 100;
        Map.Stretch := True;
        Map.Name := 'Map' + IntToStr(i);
        Map.Left := (i - 1) * 100 + 8;
        Map.Top := 8;
        Map.Picture.LoadFromFile('Test.bmp');
        Map.Parent := RichEdit1;
      end;
      // 保存元件到文件
      S := TFileStream.Create('test', fmCreate);
      try
        S.WriteComponent(RichEdit1);
        for i := 0 to RichEdit1.ControlCount - 1 do
          if RichEdit1.Controls[i] is TImage then
            S.WriteComponent(TImage(RichEdit1.Controls[i]));
      finally
        S.Free;
      end;
    end;// 再次运行程序时操作
    procedure TForm1.Button2Click(Sender: TObject);
    var
      S: TStream;
      i: Integer;
      Map: TImage;
    begin
      S := TFileStream.Create('test', fmOpenRead);
      try
    // 首先读出RichEdit
        S.ReadComponent(RichEdit1);
    // 读保存的Image
        i := 1;
        while True do// 因不知道确切的Image个数,所以采用无限循环
        try
          Map := TImage.Create(Self);
          Map.Name := 'Map' + IntToStr(i);
          S.ReadComponent(Map);
          Map.Parent := RichEdit1;
          Inc(i);
        except    //保存的Image读完,退出循环,调试时会显示错误,真正运行时不会显示错误
          Map.Free;
          Break;
        end;
      finally
        S.Free;
      end;
    end;end.
      

  6.   

    up^^
    maozefa(之源) 兄,佩服!
      

  7.   

    贴子太长了,开两个^^
    为了配合一叶知秋的程序,所以此例用了Panel做为Image的载体,一起存取。
    因为还要把位置存取下来,所以我用了一个信息文件(.info)来存文件所包括的所有图片的宽、高、左、顶的信息。可对打开文件的所有图片再次进行缩放再次存取。调试通过^^
    在此,再次感谢maozefa(之源)的引导^^
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, JvGIF, ExtDlgs, StdCtrls, ComCtrls, ExtCtrls;type
      TForm1 = class(TForm)
        RichEditNew: TRichEdit;
        BtnOpen: TButton;
        BtnSave: TButton;
        OpenPictureDialog1: TOpenPictureDialog;
        BtnAddPic: TButton;
        OpenDialog1: TOpenDialog;
        SaveDialog1: TSaveDialog;
        procedure BtnAddPicClick(Sender: TObject);
        procedure BtnOpenClick(Sender: TObject);
        procedure BtnSaveClick(Sender: TObject);
      private
        procedure FMouseMove(Sender: TObject; Shift: TShiftState; X,
          Y: Integer);
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}
    procedure ManipulateControl(WinControl: TControl; Shift: TShiftState;
                                    X, Y, Precision: integer);
                                    //Precision:精度,该方法可以在onmousemove中调用
    var
      SC_MANIPULATE: Word;
    begin
      //光标在控件的最左侧
      if (X<=Precision) and (Y>Precision) and (Y<WinControl.Height-Precision) then
      begin
        SC_MANIPULATE  := $F001;
        WinControl.Cursor := crSizeWE;  end
      else
        //光标在控件的最右侧
        if (X>=WinControl.Width-Precision) and (Y>Precision) and (Y<WinControl.Height-Precision) then
        begin
          SC_MANIPULATE  := $F002;
          WinControl.Cursor := crSizeWE;
        end
        else
          //光标在控件的最上侧
          if (X>Precision) and (X<WinControl.Width-Precision) and (Y<=Precision) then
          begin
            SC_MANIPULATE  := $F003;
            WinControl.Cursor := crSizeNS;
          end
          else
            //光标在控件的最下侧
            if (X>Precision) and (X<WinControl.Width-Precision) and (Y>=WinControl.Height-Precision) then
            begin
              SC_MANIPULATE  := $F006;
              WinControl.Cursor := crSizeNS;
            end
            else
              //光标在控件的左上角
              if (X<=Precision) and (Y<=Precision) then
              begin
                SC_MANIPULATE  := $F004;
                WinControl.Cursor := crSizeNWSE;
              end
              else
                //光标在控件的右上角
                if (X>=WinControl.Width-Precision) and (Y<=Precision) then
                begin
                  SC_MANIPULATE  := $F005;
                  WinControl.Cursor := crSizeNESW ;
                end
                else
                  //光标在控件的左下角
                  if (X<=Precision) and (Y>=WinControl.Height-Precision) then
                  begin
                    SC_MANIPULATE  := $F007;
                    WinControl.Cursor := crSizeNESW;
                  end
                  else
                    //光标在控件的右下角
                    if (X>=WinControl.Width-Precision) and (Y>=WinControl.Height-Precision) then
                    begin
                      SC_MANIPULATE  := $F008;
                      WinControl.Cursor := crSizeNWSE;
                    end
                    else
                      //光标在控件的客户区(移动整个控件)
                      if (X>5) and (Y>5) and (X<WinControl.Width-5) and 
                            (Y<WinControl.Height-5) then
                      begin
                        SC_MANIPULATE  := $F009;
                        WinControl.Cursor := crSizeAll;
                      end
                      else
                      begin
                        SC_MANIPULATE := $F000;
                        WinControl.Cursor := crDefault;
                      end;
      if Shift=[ssLeft] then
      begin
        ReleaseCapture;
        WinControl.Perform(WM_SYSCOMMAND, SC_MANIPULATE, 0);
      end;
    end;function StrLeft(const mStr: string; mDelimiter: string): string;
    { 返回左分隔字符串 }
    begin
      Result := Copy(mStr, 1, Pos(mDelimiter, mStr) - 1);
    end;function ListValue(mList: string; mIndex: Integer; mDelimiter: string = ','): string;
    { 返回列表指定位置的元素 }
    var
      I, L, K: Integer;
    begin
      if Pchar(mList)[Length(mList)-1] <> mDelimiter then
        mList:=mList + mDelimiter;
      L := Length(mList);
      I := Pos(mDelimiter, mList);
      K := 0;
      Result := '';
      while (I > 0) and (K <> mIndex) do begin
        mList := Copy(mList, I + Length(mDelimiter), L);
        I := Pos(mDelimiter, mList);
        Inc(K);
      end;
      if K = mIndex then
        Result := StrLeft(mList + mDelimiter, mDelimiter);
    end;
      

  8.   

    哎,大家搞什么呀,都把代码铁出来了,
    有方法就行了
    主要是利用FILESTREAM的WRITECOMPONENT和READCOMPONENT,然后把image想对象的属性寸起来就行了和读出来,
    比如picture 和他的位置属性
      

  9.   

    谢谢大家up了,连续发贴不许超过3次-_-!
    这是刚才那个贴的下半部分^^//建立Image的OnMouseMove调用过程
    procedure TForm1.FMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    begin
      Caption := IntToStr(X) + '/' + IntToStr(Y);
      ManipulateControl((TControl(Sender).Parent as TwinControl), Shift, X, Y, 10);
    end;//加图片
    procedure TForm1.BtnAddPicClick(Sender: TObject);
    var
      AJpg: TImage;
      APanel: TPanel;
    begin
      if Form1.OpenPictureDialog1.Execute then
      begin
        APanel := TPanel.Create(Self);
        APanel.Align := alnone;
        APanel.BevelOuter := bvNone;
        APanel.Width := Trunc(100);
        APanel.Height := Trunc(100);
        APanel.Parent := Form1.RichEditNew;    AJpg := TImage.Create(Self);
        AJpg.OnMouseMove := FMouseMove;
        AJpg.Parent := APanel;
        AJpg.Stretch := True;
        AJpg.Align := alclient;
        AJpg.Picture.LoadFromFile(Form1.OpenPictureDialog1.FileName);
      end;
    end;//打开文件
    procedure TForm1.BtnOpenClick(Sender: TObject);
    var
      S: TStream;
      i: Integer;
      Map: TImage;
      Panel: TPanel;
      tmpStrList: TStrings;
      tmpStr, tmpLeft, tmpTop, tmpWidth, tmpHeight, tmpFileName: String;
    begin
      for i := 0 to RichEditNew.ControlCount - 1 do
      begin
        RichEditNew.Controls[0].Free;
      end;  if OpenDialog1.Execute then
      begin
        tmpFileName := OpenDialog1.FileName;    tmpStrList := TStringList.Create;
        S := TFileStream.Create(tmpFileName, fmOpenRead); 
        S.ReadComponent(RichEditNew);
        tmpStrList.LoadFromFile(ExtractFilePath(tmpFileName) + ExtractFileName(tmpFileName)+'.info');    
        for i := 0 to tmpStrList.Count - 1 do
        try
          tmpStr := tmpStrList.Strings[i];
          tmpLeft := ListValue(tmpStr, 2);
          tmpTop := ListValue(tmpStr, 3);
          tmpWidth := ListValue(tmpStr, 4);
          tmpHeight := ListValue(tmpStr, 5);      Panel := TPanel.Create(Self);
          Panel.Parent := RichEditNew;
          Panel.Name := 'myPanel' + IntToStr(i+1);
          Map := TImage.Create(Self);
          Map.Parent := Panel;
          Map.Name := 'myMap' + IntToStr(i+1);
          S.ReadComponent(Panel);
          S.ReadComponent(Map);
          Panel.Parent := RichEditNew;
          Panel.Left := StrToInt(tmpLeft);
          Panel.Top := StrToInt(tmpTop);
          Panel.Width := StrToInt(tmpWidth);
          Panel.Height := StrToInt(tmpHeight);
          Map.OnMouseMove := FMouseMove;      Map.Parent := Panel;
        except
          Map.Free;
          Panel.Free;
        end;
        S.Free;
      end;
    end;//保存文件
    procedure TForm1.BtnSaveClick(Sender: TObject);
    var
      S: TStream;
      i: Integer;
      tmpStrList: TStrings;
      tmpFileName: String;
    begin
      if SaveDialog1.Execute then
      begin
        tmpFileName := SaveDialog1.FileName;
        // 保存元件到文件
        tmpStrList := TStringList.Create;
        S := TFileStream.Create(tmpFileName, fmCreate); 
        try
          S.WriteComponent(RichEditNew);
          for i := 0 to RichEditNew.ControlCount - 1 do
          begin
            if RichEditNew.Controls[i] is TPanel then
            begin
              S.WriteComponent(TPanel(RichEditNew.Controls[i]));
              if TPanel(RichEditNew.Controls[i]).Controls[0] is TImage then
              begin
                S.WriteComponent(TImage(TPanel(RichEditNew.Controls[i]).Controls[0]));
                tmpStrList.Add('myPanel'+IntToStr(i + 1)+','+'myImage'+IntToStr(i + 1)+','
                              +IntToStr(TPanel(RichEditNew.Controls[i]).Left)+','
                              +IntToStr(TPanel(RichEditNew.Controls[i]).Top)+','
                              +IntToStr(TPanel(RichEditNew.Controls[i]).Width)+','
                              +IntToStr(TPanel(RichEditNew.Controls[i]).Height));
              end;
            end;
          end;
        tmpStrList.SaveToFile(ExtractFilePath(tmpFileName) + ExtractFileName(tmpFileName)+'.info'); 
        finally
          S.Free;
          tmpStrList.Free;
        end;
      end;
    end;end.