Проект будет состоять из двух модулей (одна форма), потому что отдельный модуль (Kinto) выделен для описания класса TKentavr.
Еще один двухмодульный проект, разработка и создание которого подробно описаны, Вы найдете здесь
1-й этап: открывать файлы с картинками, создавать описания и названия к этим картинкам и сохранять в памяти в виде списка. Названия картинок помещать с окно списка ListBox, причем при щелчке по названию картинки - показывать картинку и ее описание.
2-й этап: добавить операции: сохранения созданного в памяти списка в файле на диске, чтения такого списка из файла, удаления выделенного элемента списка.
unit Kinto;
interface uses Graphics, Classes;
type
TKentavr = Class
private // доступно только в этом модуле
FBMP1: TBitMap;
FOpisan: String;
FNazvan: String;
FErr: Boolean;
public // доступно во всем проекте
property Opisan: String read FOpisan write FOpisan;
property Nazvan: String read FNazvan write FNazvan;
property BMP1: TBitMap read FBMP1 write FBMP1;
property Err: Boolean read FErr;
constructor Create;
destructor Destroy; override;
procedure Assign(Source: TPersistent);
procedure SaveToStream(Stream: TStream);
procedure LoadFromStream(Stream: TStream);
end;
implementation
constructor TKentavr.Create;
begin
inherited;
FBMP1 := TBitmap.Create;
FErr := false;
end;
destructor TKentavr.Destroy;
begin
FBMP1.Free;
inherited;
end;
procedure TKentavr.Assign(Source: TPersistent);
begin
FBMP1.Assign(Source);
end;
procedure TKentavr.SaveToStream(Stream: TStream);
Var Len: Integer;
begin
Len := Length(FNazvan); //длина строки FNazvan
Stream.Write(Len,4);//записываем длину FNazvan в поток Stream.
// Поток в данном случае - параметр метода, поэтому реально
// существующий поток должен быть передан при вызове метода.
Stream.Write(FNazvan[1],Len);// записываем FNazvan
Len := Length(FOpisan); //длина строки FOpisan
Stream.Write(Len,4);//записываем длину FOpisan
Stream.Write(FOpisan[1],Len);// записываем FOpisan
FBMP1.SaveToStream(Stream);
end;
procedure TKentavr.LoadFromStream(Stream: TStream);
Var Len, read1: Integer;
begin
read1:= Stream.Read(Len,4);
//из потока нужно прочесть 4 байта, и поместить их в
//переменную Len. Это – длина строки, которая будет прочтена.
if read1 < 4 then // когда файл закончится read1 будет = 0
begin
FErr := true; exit;
end else
FErr := false;
SetLength(FNazvan,Len); //установим размер строки = Len байт
Stream.Read(FNazvan[1],Len); //Читаем из потока Len байт, помещаем
//в строку FNazvan, начиная с 1-го символа строки.
Stream.Read(Len,4); //из потока прочтено 4 байта, помещено в
//переменную Len. Это – длина 2-й строки, которая будет прочтена.
SetLength(FOpisan,Len); //установим размер строки = Len байт
Stream.Read(FOpisan[1],Len); //Читаем из потока Len байт, помещаем
//в строку FNazvan, начиная с 1-го символа строки.
FBMP1.LoadFromStream(Stream);
end;
end.
constructor Create; - в раздел public и его реализацию
в раздел implementation модуля Kinto:
constructor TKentavr.Create;
begin
inherited;
FBMP1 := TBitmap.Create;
FErr := false; //
end;
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, ComCtrls, StdCtrls, ExtCtrls, ExtDlgs;
type
TForm1 = class(TForm)
ListBox1: TListBox;
OpenPictureDialog1: TOpenPictureDialog;
Image1: TImage;
Label2: TLabel;
memOpisan: TMemo;
MainMenu1: TMainMenu;
File1: TMenuItem;
Add: TMenuItem;
Delete: TMenuItem;
Read_Picture: TMenuItem;
ReadList: TMenuItem;
WriteList: TMenuItem;
Exit2: TMenuItem;
Label1: TLabel;
edNazvan: TEdit;
SD1: TSaveDialog;
OD1: TOpenDialog;
procedure ListBox1Click(Sender: TObject);
procedure Read_PictureClick(Sender: TObject);
procedure Exit2Click(Sender: TObject);
procedure AddClick(Sender: TObject);
procedure WriteListClick(Sender: TObject);
procedure ReadListClick(Sender: TObject);
procedure DeleteClick(Sender: TObject);
private
{ Private declarations }
Procedure Maxi;
public
{ Public declarations }
end;
var
Form1: TForm1; FName : String;
implementation uses Kinto;
{$R *.dfm}
Var Ind1: Integer; Kent,Kent2: TKentavr;
Function Max(a,b: Integer):Integer;
begin // Возвращает наибольшее из значений параметров a или b
If A > B then result := a else result := b;
end;
Procedure TForm1.Maxi;
Var Maxa: Integer;
begin // Определяет клиентские размеры формы – т к размеры картинки
// меняются
maxa := Image1.left+Image1.width + 10;
// координата правой границы картинки
ClientWidth := maxa + 2;
maxa := Max(edNazvan.Top + edNazvan.height,//Координата низа edNazvan
Image1.Top + Image1.Height); //Координата низа Image1
ClientHeight := Maxa+30;// Учет наличия полосы StatusBar1
end;
procedure TForm1.ListBox1Click(Sender: TObject);
Var Ind: Integer; //при щелчке по строке ListBox1 показываем картинку,
// связанную с этой строкой и содержимое полей объекта
begin
Ind := ListBox1.ItemIndex; // Индекс выделенной строки
If Ind < 0 then
begin beep; ShowMessage('Не выделен элемент'); exit;
end;
//ссылку на объект, который хранится в //ListBox1.Items.Objects[Ind]
// копируем в переменную-объект Kent, затем – поле Kent.FBMP копируем
// в свойство .Picture.BitMap компонента Image1
// в результате картинка появляется на форме.
Kent:= ListBox1.Items.Objects[Ind] as TKentavr;
Image1.Picture.Bitmap.Assign(Kent.BMP1);
Maxi; //Перестраиваем размеры формы, т к сменилась картинка.
MemOpisan.Clear;
MemOpisan.Text := Kent.Opisan; //Заполняем текст MemOpisan
edNazvan.Text := Kent.Nazvan; //ListBox1.Items[Ind];
end;
procedure TForm1.Read_PictureClick(Sender: TObject);
//Выбрать файл с картиной
begin
If OpenPictureDialog1.Execute then //диалог позволяет выбрать файл.
begin
Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
Maxi; //вычисляем новые клиентские размеры формы, чтобы вся картинка была видна.
end;
end;
procedure TForm1.Exit2Click(Sender: TObject);
begin //выход из программы
Application.Terminate;
end;
procedure TForm1.AddClick(Sender: TObject);
begin // Добавить сформированный объект Kent2 в список
Kent2 := TKentavr.Create;
Kent2.Assign(Image1.Picture.Bitmap);
Kent2.Opisan := MemOpisan.Text;
Kent2.Nazvan := edNazvan.Text;
Ind1:=ListBox1.Items.AddObject(edNazvan.text,Kent2);
ListBox1.ItemIndex := Ind1;
end;
procedure TForm1.WriteListClick(Sender: TObject);
//вызывается щелчком по пункту меню «Записать список в файл»
// списки храним в файлах с расширением .lst
Var ii: Integer; s1,s2: String;
Len: Integer; FS: TFileStream;
begin
if ListBox1.Count = 0 then
begin
showmessage('Список пустой. Не записываю');
exit;
end;
if SD1.Execute then FName:= SD1.FileName else exit;
FS := TFileStream.Create(FName,fmCreate);
//создаем поток для записи, связанный с файлом
for ii:=1 to ListBox1.Count do
begin Kent:= ListBox1.Items.Objects[ii-1] as TKentavr;
//циклически меняется переменная ii от 1 до числа элементов в списке.
//Переменной Kent (объявлена статически, поэтому создавать ее не надо)
//присваивается значение (ii-1)-го объекта списка, причем результат
//преобразуется к типу TKentavr при помощи оператора as TKentavr.
Kent.SaveToStream(FS);
end;
FS.Free; //закрываем и освобождаем поток.
ListBox1.Clear;
edNazvan.Clear;
memOpisan.Clear;
end;
procedure TForm1.ReadListClick(Sender: TObject);
//Щелчок по пункту меню «Прочесть список из файла»
//- чтение данных из потока.
Var s1,s2,s3: String; Kent: TKentavr;
Len,read1: Integer; FS: TFileStream;
begin
if OD1.Execute then FName:= OD1.FileName else exit;
FS := TFileStream.Create(FName,fmOpenRead);
//создан объект класса TFileStream только для чтения
ListBox1.Clear; // чистим список.
Kent := TKentavr.Create;
While not Kent.Err do //до тех пор, пока что-то прочтено
begin
Kent.LoadFromStream(FS);
if Kent.Err then break;
ListBox1.Items.AddObject(Kent.Nazvan,Kent);
Kent := TKentavr.Create;
end;
Kent.Free;
ListBox1.ItemIndex := 0; //выделим первый элемент списка (индекс =0)
// ListBox1Click(Sender); //исполним процедуру щелчка по списку ListBox1
FS.Free; //освобождаем поток, так как он не нужен (всё прочтено)
end;
procedure TForm1.DeleteClick(Sender: TObject);
begin
ListBox1.Items.Objects[ListBox1.ItemIndex].Free; // освобождаем объект.
ListBox1.DeleteSelected; // удаляем выделенный элемент
end;
end.