//Autor: Wiesław Dudek
//

unit MainFrm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls, Buttons, ExtDlgs;

type
  // Rekord z albumu
  TOsobaRec=record
    Nazwisko : String ;
    Foto : TBitmap ;
  end ;

  TAlbum=array of TOsobaRec ;

  //Budowa pliku
  // Naglowek
  TMyHeader=record
    Typ : integer ; //identyfikator pliku musi być -1000
    Rozmiar : integer ;
  end ;

  TMainForm = class(TForm)
    Label1: TLabel;
    Edit1: TEdit;
    Label2: TLabel;
    BitBtn1: TBitBtn;
    BitBtn3: TBitBtn;
    BitBtn2: TBitBtn;
    BitBtn4: TBitBtn;
    BitBtn8: TBitBtn;
    BitBtn7: TBitBtn;
    BitBtn6: TBitBtn;
    BitBtn5: TBitBtn;
    Panel1: TPanel;
    Image1: TImage;
    BitBtn9: TBitBtn;
    OpenPictureDialog1: TOpenPictureDialog;
    Label3: TLabel;
    Label4: TLabel;
    procedure FormShow(Sender: TObject);
    procedure BitBtn9Click(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure BitBtn3Click(Sender: TObject);
    procedure BitBtn2Click(Sender: TObject);
    procedure BitBtn4Click(Sender: TObject);
    procedure BitBtn5Click(Sender: TObject);
    procedure BitBtn6Click(Sender: TObject);
    procedure BitBtn7Click(Sender: TObject);
    procedure BitBtn8Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    aMyHeader : TMyHeader ;
    Osoby : TAlbum ;
    TempInt : integer ;
    NumRec : integer ;
    procedure PokazBiezacyRekord;
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.DFM}

procedure TMainForm.PokazBiezacyRekord;
begin
  if (NumRec<1) or (NumRec-1>high(Osoby)) then exit ;
  Edit1.Text:=Osoby[NumRec-1].Nazwisko ;
  Image1.Picture.Bitmap:=Osoby[NumRec-1].Foto ;
  Label3.Caption:=inttostr(NumRec) ;
  Label4.Caption:=inttostr(high(Osoby)+1) ;
end ;

procedure TMainForm.FormShow(Sender: TObject);
var fin : file ;
    IloscOdczytana, i: integer ;
    aMemoryStream:TMemoryStream ;
    Naz : string ;
    Buf : PChar ;
begin
  NumRec:=-1 ;
  if FileExists(ExtractFilePath(Application.ExeName)+'Sample.dat') then
  begin
    AssignFile(fin,ExtractFilePath(Application.ExeName)+'Sample.dat') ;
    Reset(fin,1) ; //jeśli nie podamy drugiego parametru delphi przyjmie domyślnie 128!
    //odczyt naglowka
    BlockRead(fin,aMyHeader,SizeOf(aMyHeader),IloscOdczytana) ;
    if SizeOf(aMyHeader)<>IloscOdczytana then
    begin
      ShowMessage('Błąd odczytu nagłówka z pliku Sample.dat') ;
      exit ;
    end;
    if aMyHeader.typ<>-1000 then //plik ma zły format
    begin
      ShowMessage('Zły nagłówek pliku Sample.dat') ;
      exit ;
    end;

    SetLength(Osoby,aMyHeader.Rozmiar) ;

    //wczytywanie obrazkow
    for i:=1 to aMyHeader.Rozmiar do
    begin
      //odczyt dlugosci nazwiska
      BlockRead(fin,TempInt,SizeOf(TempInt),IloscOdczytana) ;
      if SizeOf(TempInt)<>IloscOdczytana then
      begin
        ShowMessage('Błąd odczytu długości nazwiska z pliku Sample.dat') ;
        exit ;
      end;
      //odczyt nazwiska
      SetLength(Naz,TempInt) ;
      BlockRead(fin,Naz[1],TempInt,IloscOdczytana) ;
      if TempInt<>IloscOdczytana then
      begin
        ShowMessage('Błąd odczytu nazwiska z pliku Sample.dat') ;
        exit ;
      end;
      Osoby[i-1].Nazwisko:=Naz ;
      //odczyt dlugosci fotografii
      BlockRead(fin,TempInt,SizeOf(TempInt),IloscOdczytana) ;
      if SizeOf(TempInt)<>IloscOdczytana then
      begin
        ShowMessage('Błąd odczytu długości fotografii z pliku Sample.dat') ;
        exit ;
      end;
      //odczyt fotografii
      GetMem(Buf,TempInt) ;
      BlockRead(fin,Buf^,TempInt,IloscOdczytana) ;
      if TempInt<>IloscOdczytana then
      begin
        ShowMessage('Błąd odczytu fotografii z pliku Sample.dat') ;
        exit ;
      end;
      Osoby[i-1].Foto:=TBitmap.Create ;
      aMemoryStream:=TMemoryStream.Create ;
      try
        aMemoryStream.Write(Buf^,TempInt) ;
        aMemoryStream.Position:=0 ;
        Osoby[i-1].Foto.LoadFromStream(aMemoryStream) ;
      finally
        aMemoryStream.Free ;
      end ;
      Dispose(Buf) ;
    end ;

    CloseFile(fin) ;
  end ;
  BitBtn1.Click ;
end;

procedure TMainForm.BitBtn9Click(Sender: TObject);
begin
  OpenPictureDialog1.InitialDir:=GetCurrentDir ;
  if OpenPictureDialog1.Execute then
    Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName) ;
end;

procedure TMainForm.BitBtn1Click(Sender: TObject);
begin
  NumRec:=1 ;
  PokazBiezacyRekord ;
end;

procedure TMainForm.BitBtn3Click(Sender: TObject);
begin
  if NumRec<=1 then exit ;
  NumRec:=NumRec-1 ;
  PokazBiezacyRekord ;
end;

procedure TMainForm.BitBtn2Click(Sender: TObject);
begin
  if NumRec=high(Osoby)+1 then exit ;
  NumRec:=NumRec+1 ;
  PokazBiezacyRekord ;
end;

procedure TMainForm.BitBtn4Click(Sender: TObject);
begin
  NumRec:=high(Osoby)+1 ;
  PokazBiezacyRekord ;
end;

procedure TMainForm.BitBtn5Click(Sender: TObject);
begin
  SetLength(Osoby,high(Osoby)+2) ;
  NumRec:=high(Osoby)+1 ;
  Osoby[high(Osoby)].Nazwisko:=Edit1.Text ;
  Osoby[high(Osoby)].Foto:=TBitmap.Create ;
  Osoby[high(Osoby)].Foto.Assign(Image1.Picture.Bitmap) ;
  PokazBiezacyRekord ;
end;

procedure TMainForm.BitBtn6Click(Sender: TObject);
begin
  if NumRec<1 then exit ;
  Osoby[NumRec-1].Nazwisko:=Edit1.Text ;
  Osoby[NumRec-1].Foto.Assign(Image1.Picture.Bitmap) ;
  PokazBiezacyRekord ;
end;

procedure TMainForm.BitBtn7Click(Sender: TObject);
begin
  Edit1.Text:='' ;
  Image1.Picture.Bitmap:=nil ;
end;

procedure TMainForm.BitBtn8Click(Sender: TObject);
begin
  Close ;
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
var fout : file ;
    i: integer ;
    aMemoryStream:TMemoryStream ;
    Buf : PChar ;
begin
  AssignFile(fout,ExtractFilePath(Application.ExeName)+'Sample.dat') ;
  Rewrite(fout,1) ; //jeśli nie podamy drugiego parametru delphi przyjmie domyślnie 128!
  //zapis naglowka
  with aMyHeader do
  begin
    Typ:=-1000 ;
    Rozmiar:=high(Osoby)+1 ;
  end ;
  BlockWrite(fout,aMyHeader,SizeOf(aMyHeader)) ;
  //zapis adresow elementów
  for i:=0 to high(Osoby) do
  begin
    //zapis dlugości nazwiska
    TempInt:=Length(Osoby[i].Nazwisko) ;
    BlockWrite(fout,TempInt,SizeOf(TempInt)) ;
    //zapis nazwiska
    BlockWrite(fout,Osoby[i].Nazwisko[1],TempInt) ;
    aMemoryStream:=TMemoryStream.Create ;
    try
      if Assigned(Osoby[i].Foto) then Osoby[i].Foto.SaveToStream(aMemoryStream) ;
      aMemoryStream.Position:=0 ;
      GetMem(Buf,aMemoryStream.Size) ;
      if Assigned(Osoby[i].Foto) then aMemoryStream.Read(Buf^,aMemoryStream.Size) ;
      //zapis dlugosci bitmapy
      TempInt:=aMemoryStream.Size ;
      if Assigned(Osoby[i].Foto) then BlockWrite(fout,TempInt,SizeOf(TempInt)) ;
      //zapis bitmapy
      if Assigned(Osoby[i].Foto) then BlockWrite(fout,Buf^,aMemoryStream.Size) ;
      Dispose(Buf) ;
    finally
      aMemoryStream.Free ;
    end ;
  end ;
  CloseFile(fout) ;
end;

end.
