Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Использования ini-файлов в Delphi 
:(
    Опции темы
Rohoss
  Дата 9.10.2008, 01:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начальник интернета
***


Профиль
Группа: Завсегдатай
Сообщений: 1308
Регистрация: 9.10.2006
Где: Matrix

Репутация: 4
Всего: 18



Использования ini-файлов в Delphi


Если у вас полностью отсутствуют знания касательно Ini-файлов, вам следует почитать что такое Ini-файлы в википедии, а также статью о классе TIniFile, который используется для работы с файлами ini, средствами Delphi. 
Здесь же мы рассмотрим как можно использовать Ini-файлы в нашем приложении на Delphi.

Оглавления

1. Храним позицию формы и размер формы

2. Делаем мини базу данных



Храним позицию и размер формы


Итак, создадим приложения  «VCL Forms Application». В секцию uses дописываем IniFiles, это модуль в котором реализован класс TIniFile.
Теперь добавим в интерфейсный раздел класса нашей формы две процедуры, для сохранения и загрузки настроек, примерно должно быть так:

Код

  TForm1 = class(TForm)
    {Процедура для сохранения позиции и размера формы}
    procedure SaveToIni;
    {Процедура для загрузки позиции и размера формы}
    procedure LoadFromIni;
  private
    { Private declarations }
  public
    { Public declarations }
  end;


Теперь реализовываем эти процедуры, начнём с SaveToIni:

Код

procedure TForm1.SaveToIni;
begin
  with TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'config.ini') do
  begin
    {Здесь мы сохраняем высоту (Top) и отступ от
    левого края экрана (Left) нашей формы}
    WriteInteger('FormPosition', 'Top', Form1.Top);
    WriteInteger('FormPosition', 'Left', Form1.Left);
    {Следующие два метода хранят размеры формы,
    соответственно длину (Height) и ширину (Width)}
    WriteInteger('FormSize', 'Height', Form1.Height);
    WriteInteger('FormSize', 'Width', Form1.Width);
    {Ну и, конечно же, уничтожаем наш экземпляр}
    Free;
  end;
end;


Читаем комментарии в коде, там написано, что и для чего делается. Ещё хочу обратить внимания на конструктор 
Код
constructor Create(const FileName: string).
. Здесь есть маленькая особенности, параметром FileName должен быть полный путь к каталогу с программой, а не относительный, так как в противном случае он сохранит наш ini-файл в дистрибутив windows, а не в каталог с программой.
Переходим к процедуре LoadFromIni:

Код

procedure TForm1.LoadFromIni;
begin
  with TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'config.ini') do
  begin
    {Здесь мы считываем высоту (Top) и отступ от
     левого края экрана (Left) нашей формы}
    Form1.Top := ReadInteger('FormPosition', 'Top', Form1.Top);
    Form1.Left := ReadInteger('FormPosition', 'Left', Form1.Left);
    {Соответственно загружаем
     длину (Height) и ширину (Width)}
    Form1.Height := ReadInteger('FormSize', 'Height', Form1.Height);
    Form1.Width := ReadInteger('FormSize', 'Width', Form1.Width);
    {Уничтожаем экземпляр}
    Free;
  end;
end;


Здесь так же всё комментировано, хочу только обратить внимания, что у методов   WriteInteger и ReadInteger третий параметр различный, WriteInteger является процедурой, и третий параметр – это значения, которое будет записано в файл, ReadInteger – это функция, возвращающая нужное нам значение, а третий параметр у неё значение по умолчанию. Соответственно мы в нашем случае пишем туда текущее положения формы. В таком случае, если ini-файла не существует, наша форма останется такой, как и была спроектирована.
Теперь нам нужно заставить это всё работать. Как это сделать? Для сохранения настроек в файл выберем события OnClose, а для загрузки OnCreate нашей формы.  

Вот наш код на данный момент:

Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IniFiles;

type
  TForm1 = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    {Процедура для сохранения позиции и размера формы}
    procedure SaveToIni;
    {Процедура для загрузки позиции и размера формы}
    procedure LoadFromIni;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  SaveToIni;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  LoadFromIni;
end;

//-----------------------------------------------------------------------------

procedure TForm1.SaveToIni;
begin
  with TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'config.ini') do
  begin
    {Здесь мы сохраняем высоту (Top) и отступ от
     левого края экрана (Left) нашей формы}
    WriteInteger('FormPosition', 'Top', Form1.Top);
    WriteInteger('FormPosition', 'Left', Form1.Left);
    {Следующие два метода хранят размеры формы,
     соответственно длину (Height) и ширину (Width)}
    WriteInteger('FormSize', 'Height', Form1.Height);
    WriteInteger('FormSize', 'Width', Form1.Width);
    {Ну и, конечно же, уничтожаем наш экземпляр}
    Free;
  end;
end;

procedure TForm1.LoadFromIni;
begin
  with TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'config.ini') do
  begin
    {Здесь мы считываем высоту (Top) и отступ от
     левого края экрана (Left) нашей формы}
    Form1.Top := ReadInteger('FormPosition', 'Top', Form1.Top);
    Form1.Left := ReadInteger('FormPosition', 'Left', Form1.Left);
    {Соответственно загружаем
     длину (Height) и ширину (Width)}
    Form1.Height := ReadInteger('FormSize', 'Height', Form1.Height);
    Form1.Width := ReadInteger('FormSize', 'Width', Form1.Width);
    {Уничтожаем экземпляр}
    Free;
  end;
end;
end.


Теперь давайте запустим наше приложение и попробуем поменять место положения на экране и изменить размер формы. Закроем её и снова откроем, если вы всё сделали правильно, то позиция и размер формы будут сохранятся.
Теперь посмотрим содержимое нашего файла config.ini:

Код

[FormPosition]
Top=296
Left=608
[FormSize]
Height=224
Width=212


Что это за файл? Это файл, в котором хранятся настройки нашей формы.
Где он взялся? Его создал наш конструктор нашего класса 
Код

TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'config.ini')
.
FormPosition и FormSize соответственно секции нашего файла, Top, Left, Height, Width – идентификаторы, а числа, после = значения.

Делаем мини базу данных


Теперь сделаем несколько серьезней приложения, чем просто пустая форма. Создадим базу данных книг по Delphi. Вообще ini-файлы не желательно использовать для больших баз данных, так как они для этого не оптимизированы. Для ведения больших баз данных можно использовать различные СУБД и другие средства, в зависимости от задачи, но для маленькой базы можно использовать и ini, хотя при этом не желательно, чтобы эта база превышала 32Кб. Преимущество от использования ini-файла заключается также в том, что приложения будет иметь хорошую переносимость, в отличии от приложений, работающих с СУБД, так как их работоспособность зависит от наличие этой СУБД на компьютере, а если её нет, то соответственно приложения работать не будет. Это не говоря о механизме доступа к этой СУБД, который нужно носить с собой (в приложении или отдельно файлами) а он не маленький.
Итак, поменяем свойство Caption нашей формы на «База данных книг по Delphi». Теперь добавим на форму компонент TComboBox и назовём его (свойство Name) cbbBoolList, а свойство Text этого компонента очистим. Дальше добавим пять кнопок (TButton):  btnAdd, btnChange, btnRefresh, btnDelete, btnBaseDelete.  Потом, кидаем на форму панель (TPanel) и называем её pnl. На панели возмещаем компоненты :  edtAuthor: TEdit, chkIsRead: TCheckBox, seEstimation: TSpinEdit, sePrice: TSpinEdit, edtNote: TEdit. Также, возле этих компонентов желательно, поместить метки (TLabel), для отображения информации о назначении компонента.
Теперь создадим переменные, в которых будет храниться путь к каталогу программы и файла базы данных.

Код

  ProgramDir: string;
  BaseFile: string;


И присваиваем им значения

Код

procedure TForm1.FormCreate(Sender: TObject);
begin
  {Узнаём папку с программой}
  ProgramDir := ExtractFilePath(ParamStr(0));
  {Узнаем путь к нашей базе}
  BaseFile := ProgramDir + 'base.ini';
end;


В прошлой главе мы узнавали путь к ini-файлу прямо в конструкторе, но теперь мы будем обращаться к файлу чаще, поэтому будем использовать переменные.

Вот весь код:

Код

{**********************************************************}
{                                                          }
{              Модуль для демонстрации                     }
{              возможностей ini-файлов                     }
{                                                          }
{                 Разработчик: Rohoss                      }
{                Для форума: vingrad.ru                    }
{                                                          }
{**********************************************************}

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IniFiles, StdCtrls, ExtCtrls, Spin;

type
  TForm1 = class(TForm)
    btnAdd: TButton;
    cbbBoolList: TComboBox;
    btnRefresh: TButton;
    btnChange: TButton;
    pnl: TPanel;
    btnDelete: TButton;
    edtAuthor: TEdit;
    lblAuthor: TLabel;
    chkIsRead: TCheckBox;
    lblEstimation: TLabel;
    seEstimation: TSpinEdit;
    lblPrice: TLabel;
    sePrice: TSpinEdit;
    lblNote: TLabel;
    edtNote: TEdit;
    btnBaseDelete: TButton;
    procedure btnChangeClick(Sender: TObject);
    procedure btnBaseDeleteClick(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
    procedure cbbBoolListChange(Sender: TObject);
    procedure btnRefreshClick(Sender: TObject);
    procedure btnAddClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    {Процедура для сохранения позиции и размера формы}
    procedure SaveToIni;
    {Процедура для загрузки позиции и размера формы}
    procedure LoadFromIni;
    {Вносим запись в базу}
    procedure AddToBase(const BookName, Author,  Note: string; IsRead: Boolean;
      Estimation, Price: Integer);
    {Обновляем список книг}
    procedure RefreshBookList;
    {Читаем содержимое одной записи
     в компоненты на форме}
    procedure BookRead;
    {Изменяем содержимое одной записи}
    procedure ChangeBookList;
    {Удаляем книгу}
    procedure DeleteBook;
    {Удаляем базу полностью}
    procedure DeleteAllBase;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  ProgramDir: string;
  BaseFile: string;

implementation

{$R *.dfm}

{ TForm1 }
//-----------------------------------------------------------------------------

procedure TForm1.AddToBase(const BookName, Author, Note: string;
  IsRead: Boolean; Estimation, Price: Integer);
begin
   with TIniFile.Create(BaseFile) do
   begin
     WriteString(BookName, 'Author', Author);
     WriteString(BookName, 'Note', Note);
     WriteBool(BookName, 'IsRead', IsRead);
     WriteInteger(BookName, 'Estimation', Estimation);
     WriteInteger(BookName, 'Price', Price);
     Free;
   end;
end;

procedure TForm1.ChangeBookList;
begin
  AddToBase(cbbBoolList.Text, edtAuthor.Text, edtNote.Text, chkIsRead.Visible,
    seEstimation.Value, sePrice.Value);
end;

procedure TForm1.BookRead;
var
  SectionName: string;
begin
  SectionName := cbbBoolList.Text;
  with TIniFile.Create(BaseFile) do
  begin
    edtAuthor.Text := ReadString(SectionName, 'Author', '');
    chkIsRead.Checked := ReadBool(SectionName, 'IsRead', False);
    seEstimation.Value := ReadInteger(SectionName, 'Estimation', 0);
    sePrice.Value := ReadInteger(SectionName, 'Price', 0);
    edtNote.Text := ReadString(SectionName, 'Note', '');
    Free;
  end;
end;

procedure TForm1.RefreshBookList;
begin
  with TIniFile.Create(BaseFile) do
  begin
    cbbBoolList.Items.Clear;
    ReadSections(cbbBoolList.Items);
    cbbBoolList.ItemIndex := 0;
    BookRead;
    Free;
  end;
end;

//-----------------------------------------------------------------------------

procedure TForm1.DeleteAllBase;
var
  DeleteStatus: Boolean;
begin
  DeleteStatus := DeleteFile(BaseFile);
  if DeleteStatus then ShowMessage('Файл базы данных удалён')
  else ShowMessage('Не удалось удалить файл базы данных');
  RefreshBookList;
end;

procedure TForm1.DeleteBook;
var
  MessResult: Integer;
begin
  MessResult := MessageBox(0,'Вы действительно хотите удалить книгу из базы?',
    'Удаление книги', 4);
  if MessResult = 7 then Exit;
  with TIniFile.Create(BaseFile) do
  begin
    EraseSection(cbbBoolList.Text);
    Free;
  end;
  RefreshBookList;
end;

//-----------------------------------------------------------------------------

procedure TForm1.btnAddClick(Sender: TObject);
var
  BookName, Author, Note: string;
  IsRead: Boolean;
  Estimation, Price: Integer;
begin
  BookName := InputBox('Добавления книги в базу', 'Названия книги', '');
  Author := InputBox('Добавления книги в базу', 'Автор книги', '');
  if InputBox('Добавления книги в базу', 'Прочтённая книга или нет (Y или N)',
    'N') = 'Y'
  then IsRead := True
  else IsRead := False;
  Estimation := StrToInt(InputBox('Добавления книги в базу', 'Оценка', '5'));
  Price := StrToInt(InputBox('Добавления книги в базу', 'Стоимость книги', '0'));
  Note := InputBox('Добавления книги в базу', 'Комментарий к книге', '');
  AddToBase(BookName, Author, Note, IsRead, Estimation, Price);
  RefreshBookList;
end;

procedure TForm1.btnBaseDeleteClick(Sender: TObject);
begin
  DeleteAllBase;
end;

procedure TForm1.btnChangeClick(Sender: TObject);
begin
  ChangeBookList;
end;

procedure TForm1.btnDeleteClick(Sender: TObject);
begin
  DeleteBook;
end;

procedure TForm1.btnRefreshClick(Sender: TObject);
begin
  RefreshBookList;
end;

procedure TForm1.cbbBoolListChange(Sender: TObject);
begin
  BookRead;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  SaveToIni;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  {Узнаём папку с программой}
  ProgramDir := ExtractFilePath(ParamStr(0));
  {Узнаем путь к нашей базе}
  BaseFile := ProgramDir + 'base.ini';
  LoadFromIni;
  RefreshBookList;
end;

//-----------------------------------------------------------------------------

procedure TForm1.SaveToIni;
begin
  with TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'config.ini') do
  begin
    {Здесь мы сохраняем высоту (Top) и отступ от
     левого края экрана (Left) нашей формы}
    WriteInteger('FormPosition', 'Top', Form1.Top);
    WriteInteger('FormPosition', 'Left', Form1.Left);
    {Следующие два метода хранят размеры формы,
     соответственно длину (Height) и ширину (Width)}
    WriteInteger('FormSize', 'Height', Form1.Height);
    WriteInteger('FormSize', 'Width', Form1.Width);
    {Ну и, конечно же, уничтожаем наш экземпляр}
    Free;
  end;
end;

procedure TForm1.LoadFromIni;
begin
  with TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'config.ini') do
  begin
    {Здесь мы считываем высоту (Top) и отступ от
     левого края экрана (Left) нашей формы}
    Form1.Top := ReadInteger('FormPosition', 'Top', Form1.Top);
    Form1.Left := ReadInteger('FormPosition', 'Left', Form1.Left);
    {Соответственно загружаем
     длину (Height) и ширину (Width)}
    Form1.Height := ReadInteger('FormSize', 'Height', Form1.Height);
    Form1.Width := ReadInteger('FormSize', 'Width', Form1.Width);
    {Уничтожаем экземпляр}
    Free;
  end;
end;
end.


Код я старался комментировать по максимуму, но всё равно опишу, что происходит при нажатии на кнопки:
btnAdd:
Создаем множество сообщений для получении информации о книге. Эти данные добавляем с помощью процедуры AddToBase. Далее вызываем процедуру RefreshBookList, для обновления списка книг.
btnChange:
Заносим изменённые значения в базу с помощью процедуры ChangeBookList, которая также использует процедуру AddToBase. Но тут у нас добавляются значения полученные не из сообщений, а из компонентов на панели.
btnRefresh:
Вызывает процедуру RefreshBookList, которая обновляет данные в компоненте cbbBoolList.
btnDelete
:
Удалям текущую запись (книгу), с помощью процедуры DeleteBook.
btnBaseDelete:
Удаляем наш ini-файл с базой процедурой DeleteAllBase.

  К посту прикрепил проект приложения (Delphi 2006) и файл со статьёй. Просьба сильно не пинать, так как первая моя статья, однако критика и замечания приветствуются  smile 



Это сообщение отредактировал(а) Rohoss - 9.10.2008, 01:35

Присоединённый файл ( Кол-во скачиваний: 8 )
Присоединённый файл  1_Use_Ini.zip 31,03 Kb


--------------------
Файловый менеджер Explorer.Net скачать  video
PM ICQ   Вверх
THandle
Дата 9.10.2008, 01:29 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Хранитель Клуба
Group Icon
Награды: 1



Профиль
Группа: Админ
Сообщений: 3639
Регистрация: 31.7.2007
Где: Moscow, Dubai

Репутация: 65
Всего: 372



Есть пара замечаний по коду(извиняй, днем не особо всматривался...не до того было).
Код


procedure TForm1.BookRead;
var
  SectionName: string;
begin
  SectionName := cbbBoolList.Text;
  with TIniFile.Create(BaseFile) do
  begin
    edtAuthor.Text := ReadString(SectionName, 'Author', '');
    chkIsRead.Checked := ReadBool(SectionName, 'IsRead', False);
    seEstimation.Value := ReadInteger(SectionName, 'Estimation', 0);
    sePrice.Value := ReadInteger(SectionName, 'Price', 0);
    edtNote.Text := ReadString(SectionName, 'Note', '')
  end;
end;


Значит создать мы создали инюшнкин, а освобождать память за ним будет тов Пушкин... Еще бы я заюзал блок try..finally..end.
Таким образом:
Код


procedure TForm1.BookRead;
var
  SectionName: string;
begin
  SectionName := cbbBoolList.Text;
  with TIniFile.Create(BaseFile) do
  try
    edtAuthor.Text := ReadString(SectionName, 'Author', '');
    chkIsRead.Checked := ReadBool(SectionName, 'IsRead', False);
    seEstimation.Value := ReadInteger(SectionName, 'Estimation', 0);
    sePrice.Value := ReadInteger(SectionName, 'Price', 0);
    edtNote.Text := ReadString(SectionName, 'Note', '')
  finally
    Free;
  end;
end;



Еще:
Код


  MessResult := MessageBox(0,'Вы действительно хотите удалить книгу из базы?',
    'Удаление книги', 4);
  if MessResult = 7 then Exit;


Откуда взят эти числа? 4, 7? Нипанятна. Лучше использовать стандартные константы.


Дальше:
Код


  if InputBox('Добавления книги в базу', 'Прочтённая книга или нет (Y или N)',
    'N') = 'Y'
  then IsRead := True
  else IsRead := False;


Заче оно?

Так лучше:
Код


  IsRead := InputBox('Добавления книги в базу', 'Прочтённая книга или нет (Y или N)', 'N') = 'Y';


Next...

Код

Price := StrToInt(InputBox('Добавления книги в базу', 'Стоимость книги', '0'));


Если юзер введет текст, то что тогда?

Использовать TryStrToInt.


Пока все...
PM   Вверх
Bose
Дата 9.10.2008, 01:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1458
Регистрация: 5.3.2005
Где: Riga, Latvia

Репутация: 23
Всего: 51



Вместо TIniFile лучше использовать TMemIniFile. Быстрее работает. 
PM MAIL WWW Skype   Вверх
Rohoss
Дата 9.10.2008, 01:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начальник интернета
***


Профиль
Группа: Завсегдатай
Сообщений: 1308
Регистрация: 9.10.2006
Где: Matrix

Репутация: 4
Всего: 18



THandle, спасибо за критику smile .

В процедуре BookRead действительно забыл освободить память, уже исправил.

Блоки обработки исключений тут не использую, дабы лишний раз не усложнять код. Он всё же рассчитан на новичков  smile 



--------------------
Файловый менеджер Explorer.Net скачать  video
PM ICQ   Вверх
Qu1nt
Дата 9.10.2008, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 602
Регистрация: 13.1.2007

Репутация: 18
Всего: 50



Давайте напишем ещё пару одинаковых статей на тривиальные темы? По-моему, THandle в своей статье все изложил максимально доступно.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0541 ]   [ Использовано запросов: 23 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.