Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Урок 9 - Работа с INI файлами

Ведущий раздела KOL и MCK: Анатолий aka XVeL
Автор: Борис Моренко
WEB-сайт: http://kol.mastak.ru

Полную версию библиотеки KOL и MCK можно скачать здесь.

Если вы не являетесь любителем забивать свои и чужие реестры мегабайтами мусора, или просто не надеетесь на сохранность информации в нем (когда нибудь Windows наверняка умрет), то вам надо обратить свои взоры на старые добрые Ini-файлы.

В KOL работа с ini организованна с помощью объекта TIniFile.
Для того чтобы открыть ini-файл (и одновременно создать TIniFile), надо воспользоваться функцией OpenIniFile.
Свойство Mode отвечает за то, что вы будете делать с ini файлом : производить запись или чтение. Для записи вы должны прировнять Mode к ifmWrite, и соответственно для чтения к ifmRead. По умолчанию (при открытии) Mode = ifmRead, т.е. для чтения.

Для чтения/записи данных из ini используют 4 функции. Их описание приведено в таблице :

Функция Выполняемое действие

ValueInteger

Чтение/запись данных Value типа integer под именем Key

function ValueInteger( const Key: String; Value: Integer ): Integer;

ValueString

Чтение/запись данных Value типа string под именем Key

function ValueString( const Key: String; const Value: String ): String;

ValueBoolean

Чтение/запись данных Value типа boolean под именем Key

function ValueBoolean( const Key: String; Value: Boolean ): Boolean;

ValueData

Чтение/запись данных на которые указывает Value длинной Count под именем Key

function ValueData( const Key: String; Value: Pointer; Count: Integer ): Boolean;

Еще раз повторюсь и напомню, что чтение или запись происходит в зависимости от того чему равно свойство Mode.

Как известно ini файлы построены по следующему принципу

[Section1]
Key1=Value
Key2=Value
...
[Section2]
Key1=Value
Key1=Value
...
Section - секция (раздел) ini файла.
Key - имя переменной
Value - Переменная которая записывается под именем Key
(Кто этого не знал, может открыть любой ini файл и убедится в этом).
За то из какой секции происходит чтение (или запись) отвечает свойство Section. Для того чтобы получить список секций надо обратится к GetSectionNames. А для получения данных из секции, надо воспользоваться SectionData. И у первой и второй процедуры данные записываются в объект типа pStrList (список строк).
Я про него пока ничего не рассказывал, но он мало чем отличается от от VCL аналога TStringList. Но отличия все-таки есть, и к сожалению не в пользу pStrList. У pStrList нет таких свойств как Name и Value, а они бы не помешали, так как SectionData возвращает список из переменных и их значений в том же виде, в каком они записаны в ini файле (т.е разделенные знаком равно).
Ну это не такая и большая проблема :) В подтверждение этого, маленький примерчик простенького ini-редактора.
Программа внешне состоит из двух списков (List1 и List2). В List1 заносятся имена секторов, а в List2 список переменных и их значения. Сверху два поля (edName и edDan), в которые заносятся имя переменной и ее значение, когда происходит двойной клик по List2. Поле edDan (в него заносятся значение) можно редактировать.
program Primer_2; 
 
uses 
  windows, 
  messages, 
  kol; 
 
var 
 Form, 
 panTop, 
 buWrite, 
 edDan,edName, 
 List1,List2 : pControl; 
 dialog : pOpenSaveDialog; 
 strList : pStrList; 
 ini : pIniFile; 
 i : integer; 
 
/////////////////////////////////////////////////////////////////////

// обработка клика по кнопке "записать "
Procedure ClickOnBuWrite( Dummy : Pointer; Sender : PControl ); 
begin 
  if edName.Text = '' then Exit; 
  ini.Mode := ifmWrite; 
  ini.ValueString(edName.Text, edDan.text); 
  ini.Mode := ifmRead; 
end; 
///////////////////////////////////////////////////////////////////// 
Procedure ClickOnList2( Dummy : Pointer; Sender : PControl ); 
var 
  s : string; 
  i : integer; 
begin 
  s := List2.Items[List2.CurIndex]; 
  i := IndexOfChar(s, '='); 
  edName.Text := Copy(s, 0, i - 1); 
  edDan.Text := CopyEnd(s, i + 1); 
end; 
///////////////////////////////////////////////////////////////////// 
Procedure ClickOnList1( Dummy : Pointer; Sender : PControl ); 
var 
  j : integer; 
begin 
  edName.Clear ; 
  edDan.Clear ; 
  j := List1.CurIndex; 
  // заносим в List2 данные, которые находятся в j-ой секции 
  strList.Clear ; 
  List2.Clear ; 
  ini.Section := List1.Items[j]; 
  ini.SectionData(strList); 
  for i := 0 to strList.Count-1 do 
    List2.Items[i]:=strList.Items[i]; 
end; 
///////////////////////////////////////////////////////////////////// 
begin 
  Applet := NewApplet('Пример #2'); 
 
  dialog := NewOpenSaveDialog('Выбор ini', '', []); 
  dialog.Filter := '*.ini|*.ini|все|*.*'; 
  dialog.OpenDialog := true; 
  if dialog.Execute then 
    ini := OpenIniFile(dialog.Filename) 
  else 
    exit; 
 
  //----------- делаем интерфейс ------------------------ 
  Form := NewForm(Applet, 'Работа с Ini файлами').setSize(400, 300); 
  Form.Font.FontName := 'MS Sans Serif'; 
  Form.Font.FontHeight := 9; 
  Form.Style := WS_BORDER or WS_SYSMENU or WS_VISIBLE; 
 
  panTop := NewPanel(Form, esRaised ).SetAlign(caTop) ; 
  panTop.Height := 60 ; 
  buWrite := NewButton(panTop, 'Записать'); 
  buWrite.OnClick := TOnEvent( MakeMethod( nil, @ClickOnBuWrite ) ); 
  
  edName := NewEditBox(panTop,[eoReadOnly]).PlaceDown; 
  edDan := NewEditBox(panTop, []).PlaceRight; 
  edDan.Width := Form.Width - edName.Width - 30; 
  
  strList:= NewStrList; 
 
  List1 := NewListBox(Form,[]).setAlign(caLeft); 
  List2 := NewListBox(Form,[]).setAlign(caClient); 
  //--------------------------------------------------- 
 
  // заносим в List1 список секций 
  ini.GetSectionNames(strList); 
  for i := 0 to strList.Count - 1 do 
    List1.Items[i] := strList.Items[i]; 
 
  List1.OnChange := TOnEvent( MakeMethod( nil, @ClickOnList1 ) ); 
 
  // показываем данные из 0-ой секции 
  List1.CurIndex := 0; 
  ClickOnList1(nil, nil); 
 
  List2.OnClick := TOnEvent( MakeMethod( nil, @ClickOnList2 ) ); 
  run(Applet); 
end.
Исходный текст : 2,64 Кб ; размер программы: 32,5Кб(без сжатия и замены System).

А теперь таблица подытоживающая все вышесказанное, а также рассказывающая про свойства pIniFile, которые не были затронуты:

Cвойство Описание
FileName Имя ini файла
Mode Отвечает в каком режиме находится Ini файл: для чтения или для записи
Section Секция из которой (или в которую) идет чтение (или запись)
GetSectionNames Читает список секций в этом ini-файле
SectionData Читает данные из текущей секции
ClearAll Удаляет все секции в ini-файле
ClearSection Удаляет текущую секцию
ClearKey Удаляет ключ (переменную)
Проект Delphi World © Выпуск 2002 - 2004
Автор проекта: ___Nikolay