Delphi Kompendium Roz6

background image

Logowanie | Rejestracja | Forum | Pomoc | Reklama | Szukaj

Strona główna :: Delphi :: Kompendium

Edytuj

Historia

Rozdział 6

Rejestry i pliki INI

Czy nie zastanawiało Cię nigdy, gdzie tak naprawdę te wszystkie programy przechowują informacje o
użytkowniku oraz opcje i inne ustawienia? W dziewięćdziesięciu procentach takich przypadków autorzy tychże
programów musieli skorzystać z Rejestru Windows lub plików INI. Być może nie wiesz dokładnie, czym jest
Rejestr lub pliki INI, więc na samym początku tego rozdziału poświęcę parę stron na omówienie budowy
zarówno Rejestru, jak i plików INI.

Spis treści

1 Czym jest Rejestr Windows?

1.1 Podstawowe klucze

1.2 Podstawowe pojęcia

2 Pliki INI

2.1 Budowa

3 Rejestr kontra plik INI

4 Klasa TRegistry

4.1 Tworzenie nowych kluczy

4.2 Otwieranie istniejących kluczy

4.3 Usuwanie kluczy

4.4 Dodawanie wartości

4.4.1 Pozostałe funkcje służące do zapisu danych

4.4.1.1 WriteTime

4.4.1.2 WriteFloat

4.4.1.3 WriteDate, WriteDateTime

4.4.1.4 WriteCurrency

4.4.1.5 WriteBool

4.4.1.6 WriteBinaryData

4.5 Odczyt danych

4.6 Inne funkcje operujące na Rejestrze

4.6.1 DeleteValue

4.6.2 GetDataInfo

4.6.3 GetDataSize

4.6.4 GetDataType

4.6.5 GetKeyInfo

4.6.6 GetKeyNames

4.6.7 GetValueNames

4.6.8 HasSubKeys

4.6.9 KeyExists

4.6.10 LoadKey

4.6.11 SaveKey

4.6.12 MoveKey

4.6.13 RootKey

5 Praktyczny przykład

6 Klasa TINIFile

6.1 Tworzenie nowego pliku INI

6.2 Zapisywanie danych

6.3 Odczyt danych

6.4 Funkcje związane z operacjami na sekcjach

6.4.1 ReadSection

6.4.2 ReadSections

6.4.3 ReadSectionValues

6.4.4 EraseSection

6.5 Przykładowy program

7 Podsumowanie

W tym rozdziale:

dowiesz się, czym jest Rejestr Windows oraz pliki INI;
zaczniesz swobodnie korzystać z Rejestru Windows;
dowiesz się, jak uruchamiać swój program po starcie systemu;
nauczysz się korzystać z plików INI.

Czym jest Rejestr Windows?

Rejestr Windows to gąszcz informacji na temat ustawień systemowych oraz ustawień programów działających
na komputerze. Uszkodzenie rejestru może spowodować problemy z uruchomieniem systemu, należy zatem
obchodzić się z nim dość delikatnie.

Chociaż Microsoft może temu zaprzeczać, wiadomo, że Rejestr Windows jest jednym z najważniejszych
elementów systemu; zawiera wiele kluczy oraz wartości niezwykle istotnych dla działania systemu.
Rejestr Windows, a właściwie Edytor Rejestru, został przedstawiony na rysunku 6.1.

Delphi

Artykuły
Kompendium
Gotowce
FAQ
.NET

Turbo Pascal

FAQ

PHP

FAQ

Java

FAQ

C/C++

Artykuły
FAQ

C#

Wprowadzenie

Assembler

FAQ

(X)HTML
CSS
JavaScript
Z pogranicza
Algorytmy

WIĘCEJ

»

Delphi
C/C++
Turbo Pascal
Assembler
PHP

Programy
Dokumentacja
Kursy
Komponenty

WIĘCEJ

»

Delphi :: Kompendium :: Rozdział 6 - 4programmers.net

http://4programmers.net/Delphi/Kompendium/Rozdzia%C5%82_6

1 z 12

2009-03-14 15:33

background image

Rysunek 6.1. Okno Edytora Rejestru

Program przedstawiony na rysunku 6.1 można uruchomić, wybierając z menu Start/Uruchom i wpisując w
okienku regedit.

Jako że bez zachowania należytej ostrożności można bardzo łatwo ?zepsuć? Rejestr,
zalecane jest utworzenie jego kopii zapasowej w postaci pliku *.reg. Można tego dokonać,
wybierając z menu Rejestr pozycję Eksportuj plik rejestru. W oknie musisz wpisać nazwę
pliku oraz zaznaczyć opcję Wszystko. Po zakończeniu operacji w podanej lokalizacji
utworzony zostanie plik, po którego uruchomieniu Rejestr zostanie uaktualniony według
wartości zawartych w kopii.

Podstawowe klucze

Rejestr Windows dzieli się na kilka podstawowych kluczy głównych: HKEY_CLASSES_ROOT,
HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CURRENT_CONFIG i HKEY_DYN_DATA.
Tylko w tych kluczach głównych możesz tworzyć nowe klucze oraz wartości. Właściwie powinieneś napisać swój
program tak, aby tworzył nowe klucze w gałęzi HKEY_CURRENT_USER, gdyż to ona jest przeznaczona dla
programów zewnętrznych, ale oczywiście nic nie stoi na przeszkodzie, aby wpisywać dane do innych gałęzi.

Podstawowe pojęcia

Rejestr Windows dzieli się na klucze oraz wartości. W celu zrozumienia zasady działania Rejestru oraz dalszej
terminologii używanej przeze mnie w tym rozdziale należy wyjaśnić te pojęcia.

Można przyjąć, że kluczami są gałęzie (foldery) przedstawione w Edytorze Rejestru. Takie foldery (klucze)
mogą zawierać bardzo wiele wartości, które są danymi. W każdym kluczu znajduje się tzw. wartość domyślna,
która nie zawiera żadnych danych. Istnieje możliwość tworzenia kilku typów wartości: tekstowa, binarna
lub DWORD. Wartość tekstowa służy do przechowywania tekstu. Wartość DWORD to najzwyklejsze dane w postaci
liczb, natomiast wartość binarna umożliwia przechowywanie większej ilości danych.

Pliki INI

Pliki INI to zwykłe pliki tekstowe z rozszerzeniem *.ini, o specyficznej budowie opartej na jednolitym
standardzie. Pliki INI, podobnie jak Rejestr, służą do przechowywania ustawień aplikacji. Dane te są jednak
przechowywane w plikach, co daje w efekcie mniejszy poziom bezpieczeństwa (każdy może otworzyć sobie taki
plik w Notatniku Windows) niż Rejestr.

Budowa

Podstawowym kryterium podziału plików INI są sekcje. W każdej sekcji mogą znajdować się różne klucze i
wartości. Przykładowa zawartość pliku INI (w tym przypadku jest to plik win.ini) wygląda tak:

[Desktop]
Wallpaper=(None)
TileWallpaper=1

WallpaperStyle=0

W tym przypadku sekcją jest wiersz [Desktop]. Wymagane jest wpisywanie nazwy nowej sekcji w nawiasach
kwadratowych, dzięki czemu przy odwołaniu do sekcji w programie system ?wie?, które wiersze będą nas
interesowały.

W sekcji mogą znajdować się klucze i wartości, oddzielone znakiem równości.

Klucz=wartość

Do wartości mogą być przypisywane różne dane, takie jak liczby czy tekst. Każda wartość musi być oddzielona
od klucza znakiem nowego wiersza. Oznacza to, że każdy klucz musi być zapisany jeden pod drugim.
Istnieje możliwość stosowania w plikach INI komentarzy. Komentarze, tak jak w języku programowania, nie są
interpretowane przez system. W plikach INI istnieją jedynie komentarze jednowierszowe, które muszą
rozpoczynać się od znaku średnika (;).

Rejestr kontra plik INI

Czasem podczas projektowania aplikacji będziesz musiał zastanowić się, czy zastosować pliki INI czy może
Rejestr Windows. Jest to wbrew pozorom ważna decyzja, która podjęta musi zostać po przemyśleniu paru
spraw.

Rejestr Windows daje większe bezpieczeństwo, gdyż użytkownik chcąc zmienić pewne wartości, będzie musiał
wyszukiwać je w całym gąszczu różnych kluczy. Zawartość pliku INI może być zmieniona praktycznie przez
każdego, nawet początkującego. Należy więc wziąć pod uwagę to, że użytkownik nieumyślnie może
spowodować zmianę zawartość pliku INI, a tym samym doprowadzić do nieprawidłowego funkcjonowania
programu.

RSS | Forum | Pastebin |

Regulamin | Pomoc | Usuń

cookies | Prawa autorskie |

Kontakt | Reklama

Copyright © 2000-2006 by Coyote Group 0.9.3-pre3

Czas generowania strony: 1.9504 sek. (zapytań SQL:

12)

Delphi :: Kompendium :: Rozdział 6 - 4programmers.net

http://4programmers.net/Delphi/Kompendium/Rozdzia%C5%82_6

2 z 12

2009-03-14 15:33

background image

Z drugiej jednak strony można skorzystać z plików INI, aby dać możliwość zmiany pewnych ustawień w
programie. Taką konstrukcję zastosowali projektanci interpretera PHP. Użytkownik chcąc zmienić pewne
ustawienia, musi ?pogrzebać? trochę w pliku INI. Jest to jednak opcja przeznaczona dla bardziej
zaawansowanych programistów.

Ostatni aspekt. Podczas usunięcia systemu skasowany zostanie także rejestr Windows, a tym samym
ustawienia naszego programu. Plik INI może być umieszczony w katalogu z programem, tak więc reinstalacja
systemu nie oznacza utracenia zapisanych w owym pliku danych.

Klasa TRegistry

VCL zwalnia nas w dużym stopniu z mozolnego korzystania z funkcji API w celu operowania na Rejestrze.
Udostępnia bowiem klasę TRegistry, która znajduje się w module Registry. Pierwszą rzeczą, którą musisz
wykonać, jest dodanie do listy

uses

modułu Registry.

Tworzenie nowych kluczy

Podstawową operacją na Rejestrze jest otwarcie konkretnego klucza, zamknięcie go po zakończeniu operacji lub
stworzenie nowego.

Stworzenie nowego klucza realizuje metoda CreateKey, w której należy podać jedynie nazwę klucza.

procedure TMainForm.

btnCreateClick

(

Sender:

TObject

)

;

var
Reg : TRegistry;
begin
Reg := TRegistry.

Create

;

Reg.

CreateKey

(

'Moja aplikacja 1.0'

)

;

Reg.

Free

;

end;

Klasa TRegistry jest zwykłą klasą VCL, należy więc utworzyć ją przed rozpoczęciem korzystania z Rejestru, a
po zakończeniu ? zwolnić za pomocą metody Free.

Domyślnie wszystkie operacje na rejestrze odbywają się na kluczu głównym
HKEY_CURRENT_USER

. Jeżeli chcesz dokonać zmian, w innym kluczu głównym należy

przypisać jego nazwę do zmiennej RootKey z klasy TRegistry.

Powyższy kod spowoduje tworzenie nowego klucza Moja Aplikacja 1.0 w kluczu głównym HKEY_CURRENT_USER
(rysunek 6.2).

Rysunek 6.2. Zaznaczony nowo utworzony klucz w Rejestrze Windows

Otwieranie istniejących kluczy

Metoda OpenKey z klasy TRegistry realizuje otwarcie istniejącego klucza lub utworzenie nowego. Tak
naprawdę do tworzenia nowych kluczy rzadko stosowana jest funkcja CreateKey ? znacznie częściej
programiści korzystają z metody OpenKey, która może zarówno otwierać klucze, jak i tworzyć nowe!

Oto przykład otwarcia istniejącego klucza:

procedure TMainForm.

btnOpenClick

(

Sender:

TObject

)

;

var
Reg : TRegistry;
begin
Reg := TRegistry.

Create

;

if Reg.

OpenKey

(

'Moja aplikacja 1.0'

,

False

)

then

ShowMessage

(

'Klucz otwarty!'

)

else

ShowMessage

(

'Błąd!'

)

;

Reg.

Free

;

end;

Funkcja OpenKey zwraca True, jeżeli klucz został otwarty, lub False, jeżeli nie udało się otworzyć klucza. Drugi
parametr owej funkcji określa, czy klucz ma zostać utworzony w przypadku, gdy nie istnieje (True), lub czy
funkcja po prostu ma zwrócić wartość False (nie udało się utworzyć ani otworzyć klucza).

Po zakończeniu korzystania z kluczy należy klucz zamknąć poleceniem CloseFile, aczkolwiek nie jest to
wymagane, jeżeli jednocześnie kończysz używanie klasy ? wówczas należy wywołać metodę Free, która
zamknie klucz oraz zwolni samą klasę. Metoda CloseFile jest używana w przypadku, gdy operujesz na wielu
kluczach Rejestru. Przykładowo: otwierasz jeden, wprowadzasz stosowne zmiany, zamykasz klucz i otwierasz
inny.

Delphi :: Kompendium :: Rozdział 6 - 4programmers.net

http://4programmers.net/Delphi/Kompendium/Rozdzia%C5%82_6

3 z 12

2009-03-14 15:33

background image

Usuwanie kluczy

Chcąc usunąć klucz, należy wywołać metodę DeleteKey. Jej użycie jest proste, ponieważ posiada tylko jeden
parametr, który jest nazwą klucza. Funkcja zwraca True, jeżeli operacja się powiedzie, lub ? w przeciwnym
wypadku ? False.

...
Reg.DeleteKey('Moja Aplikacja 1.0');

...

Poczyńmy jeszcze jedno zastrzeżenie, żeby uniknąć nieporozumień! Parametr w funkcjach OpenKey, CreateKey
i DeleteKey to w rzeczywistości nie nazwa klucza, lecz ścieżka do niego. Nasz klucz może być umieszczony w
sporym ?gąszczu? innych kluczy, stąd należy podać pełną ścieżkę:

Reg.

DeleteKey

(

'Klucze\Inny klucz\Moja Aplikacja 1.0'

)

;

Dodawanie wartości

Bardzo łatwo zapamiętać metody powodujące zapis danych do Rejestru, gdyż nazywane są one według wzorca
WriteXXX, gdzie w miejsce XXX należy podać typ danych przeznaczonych do dodania. Czyli np. chcąc zapisać w
Rejestrze dane typu String, stosujemy funkcję WriteString.

Każda z funkcji zapisujących dane posiada dwa parametry. Pierwszy z nich to nazwa wartości w kluczu, a drugi
parametr to dane do zapisania. Przykładowo jeśli chcesz zapisać w Rejestrze dane typu String, musisz
skorzystać z kodu:

Reg.

WriteString

(

'City'

, edtCity.

Text

)

;

Spowoduje to utworzenie lub nadpisanie wartości City z danymi zapisanymi w komponencie edtCity.

Oto przykład zapisania kilku wartości do klucza:

procedure TMainForm.

btnSaveClick

(

Sender:

TObject

)

;

var
Reg : TRegistry;
begin
Reg := TRegistry.

Create

;

if Reg.

OpenKey

(

'Moja aplikacja 1.0'

,

False

)

then

ShowMessage

(

'Klucz otwarty!'

)

else

ShowMessage

(

'Błąd!'

)

;

Reg.

WriteString

(

'FName'

, edtFName.

Text

)

;

Reg.

WriteString

(

'SName'

, edtSName.

Text

)

;

Reg.

WriteString

(

'City'

, edtCity.

Text

)

;

Reg.

WriteString

(

'Country'

, edtCountry.

Text

)

;

Reg.

WriteInteger

(

'Pesel'

,

StrToInt

(

edtPesel.

Text

))

;

Reg.

Free

;

end;

Na rysunku 6.3 przedstawiony jest klucz Rejestru, który przedstawia zapisane i wprowadzone przez program
wartości.

Rysunek 6.3. Zapisane przez program wartości

Pozostałe funkcje służące do zapisu danych

Zapoznałeś się już z dwiema funkcjami służącymi do zapisu danych ? WriteInteger oraz WriteString.
Oczywiście nie są to jedyne funkcje ? wszystkie pozostałe opisuję i przedstawiam poniżej:

WriteTime

procedure

WriteTime

(

const

Name

:

String

; Value:

TDateTime

)

;

Funkcja WriteTime służy do zapisu czasu. Dzięki niej możesz np. zapisać czas ostatniego uruchomienia
programu.

...

Reg

.

WriteTime

(

'Czas'

,

Now

)

;

...

Delphi :: Kompendium :: Rozdział 6 - 4programmers.net

http://4programmers.net/Delphi/Kompendium/Rozdzia%C5%82_6

4 z 12

2009-03-14 15:33

background image

Funkcja Now zwraca aktualny czas. Chcąc zapisać także datę, zastosuj funkcję WriteDate lub WriteDateTime.

WriteFloat

procedure

WriteFloat

(

const

Name

:

String

; Value:

Double

)

;

Funkcja WriteFloat spowoduje stworzenie w Rejestrze nowego klucza z wartością zmiennoprzecinkową typu
Double

.

WriteDate, WriteDateTime

procedure

WriteDate

(

const

Name

:

String

; Value:

TDateTime

)

;

procedure

WriteDateTime

(

const

Name

:

String

; Value:

TDateTime

)

;

Wywołanie pierwszej funkcji spowoduje utworzenie w Rejestrze klucza zawierającego jedynie datę, a drugiej
(WriteDateTime) ? zapisanie daty oraz czasu.

WriteCurrency

procedure

WriteCurrency

(

const

Name

:

String

; Value:

Currency

)

;

Procedura WriteCurrency powoduje zapisanie w Rejestrze wartości zmiennoprzecinkowej typu Currency.

WriteBool

procedure

WriteBool

(

const

Name

:

String

; Value:

Boolean

)

;

Jeżeli chcesz zapisać w Rejestrze wartość typu Boolean (True lub False), skorzystaj z procedury WriteBool.

WriteBinaryData

procedure

WriteBinaryData

(

const

Name

:

String

;

var

Buffer; BufSize:

Integer

)

;

Procedura WriteBinaryData umożliwia zapisanie w Rejestrze wartości nieokreślonej. Drugi parametr musi
zawierać wskazanie zmiennej (bufor), a ostatni parametr określa rozmiar bufora.

Maksymalna wielkość danych, jakie mogą być zapisane w Rejestrze, to 2 048 bajtów.
Przykład użycia:

var
Buffer :

array

[

0

..

255

]

of

char

;

...

Buffer

:=

'Jakiś tekst może być lub coś innego'

;

Reg.

WriteBinaryData

(

?Nazwa?, Buffer,

SizeOf

(

Buffer

))

;

...

Odczyt danych

Wiadomo, że zapisujemy dane równie często, jak je odczytujemy. Odczytywanie i zapisywanie danych jest
bardzo podobne ? różnią się jedynie nazwy poleceń. W trakcie odczytywania danych stosujemy polecenia
ReadXXX, gdzie XXX jest nazwą typu do odczytania. Kolejna różnica jest taka, że polecenia z rodziny ReadXXX
to funkcje, a nie procedury ? jak to miało miejsce podczas zapisywania danych.

Posłużmy się przykładem z poprzedniego podpunktu. Tam program zapisywał w Rejestrze parę informacji,
takich jak imię, nazwisko itp. Poniższy przykład ilustruje sposób odczytu tych danych:

procedure TMainForm.

FormCreate

(

Sender:

TObject

)

;

var
Reg : TRegistry;
begin
Reg := TRegistry.

Create

;

if Reg.

KeyExists

(

'Moja aplikacja 1.0'

)

then

begin

Reg.

OpenKey

(

'Moja aplikacja 1.0'

,

False

)

;

edtFName.

Text

:= Reg.

ReadString

(

'FName'

)

;

edtSName.

Text

:= Reg.

ReadString

(

'SName'

)

;

edtCity.

Text

:= Reg.

ReadString

(

'City'

)

;

edtCountry.

Text

:= Reg.

ReadString

(

'Country'

)

;

edtPesel.

Text

:=

IntToStr

(

Reg.

ReadInteger

(

'Pesel'

))

;

end;

Reg.

Free

;

end;

Kod jest umieszczony w zdarzeniu OnCreate, co spowoduje odczytanie danych zaraz po uruchomieniu aplikacji.
Zauważ, że przed samym procesem odczytu następuje sprawdzanie, czy taki klucz istnieje (funkcja
KeyExists

). Może się bowiem zdarzyć tak, że program jest uruchamiany po raz pierwszy i taki klucz nie

istnieje.

Listing 6.1 przedstawia cały kod programu, a na rysunku 6.4 zaprezentowano program w trakcie działania.

Listing 6.1. Kod źródłowy modułu

unit MainFrm;

interface

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

type
TMainForm =

class

(

TForm

)

btnSave: TButton;
gbInfo: TGroupBox;
lblFName: TLabel;
lblSName: TLabel;
lblCity: TLabel;
lblCountry: TLabel;

Delphi :: Kompendium :: Rozdział 6 - 4programmers.net

http://4programmers.net/Delphi/Kompendium/Rozdzia%C5%82_6

5 z 12

2009-03-14 15:33

background image

lblPesel: TLabel;
edtFName: TEdit;
edtSName: TEdit;
edtCity: TEdit;
edtCountry: TEdit;
edtPesel: TEdit;

procedure btnSaveClick

(

Sender:

TObject

)

;

procedure FormCreate

(

Sender:

TObject

)

;

private

{ Private declarations }

public

{ Public declarations }

end;

var
MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.

btnSaveClick

(

Sender:

TObject

)

;

var
Reg : TRegistry;
begin
Reg := TRegistry.

Create

;

if Reg.

OpenKey

(

'Moja aplikacja 1.0'

,

True

)

then

ShowMessage

(

'Klucz otwarty!'

)

else

ShowMessage

(

'Błąd!'

)

;

Reg.

WriteString

(

'FName'

, edtFName.

Text

)

;

Reg.

WriteString

(

'SName'

, edtSName.

Text

)

;

Reg.

WriteString

(

'City'

, edtCity.

Text

)

;

Reg.

WriteString

(

'Country'

, edtCountry.

Text

)

;

Reg.

WriteInteger

(

'Pesel'

,

StrToInt

(

edtPesel.

Text

))

;

Reg.

Free

;

end;

procedure TMainForm.

FormCreate

(

Sender:

TObject

)

;

var
Reg : TRegistry;
begin
Reg := TRegistry.

Create

;

if Reg.

KeyExists

(

'Moja aplikacja 1.0'

)

then

begin

Reg.

OpenKey

(

'Moja aplikacja 1.0'

,

False

)

;

edtFName.

Text

:= Reg.

ReadString

(

'FName'

)

;

edtSName.

Text

:= Reg.

ReadString

(

'SName'

)

;

edtCity.

Text

:= Reg.

ReadString

(

'City'

)

;

edtCountry.

Text

:= Reg.

ReadString

(

'Country'

)

;

edtPesel.

Text

:=

IntToStr

(

Reg.

ReadInteger

(

'Pesel'

))

;

end;

Reg.

Free

;

end;

end.

Rysunek 6.4. Program w trakcie działania

Nie będę marnował już papieru na opis wszystkich funkcji służących do odczytu danych z Rejestru, gdyż ich
zastosowanie i nazwy można odkryć intuicyjne. W poprzednim podpunkcie przedstawiłem wszystkie procedury
do zapisu danych ? jeżeli chcesz odczytać dane, wystarczy w nazwach tych procedur zamienić fragment Write
na Read.

Inne funkcje operujące na Rejestrze

Przedstawione dotychczas w tym rozdziale funkcje nie są jedynymi, które można zastosować wraz z Rejestrem.
Poniżej przedstawiam opis i deklaracje pozostałych.

DeleteValue

function

DeleteValue

(

const

Name

:

String

)

:

Boolean

;

Do kasowania całych kluczy można użyć funkcji DeleteKey, natomiast aby usunąć poszczególne wartości z tych
kluczy, należy zastosować funkcję DeleteValue. Parametr Name jest nazwą wartości, która ma zostać
skasowana. Funkcja zwraca True, jeżeli operacja się powiedzie.

GetDataInfo

function

GetDataInfo

(

const

ValueName:

String

;

var

Value: TRegDataInfo

)

:

Boolean

;

Funkcja GetDataInfo dostarcza informacji na temat danych umieszczonych w rejestrze. Pierwszym
parametrem musi być nazwa wartości, natomiast drugi parametr musi być wskazaniem na strukturę

Delphi :: Kompendium :: Rozdział 6 - 4programmers.net

http://4programmers.net/Delphi/Kompendium/Rozdzia%C5%82_6

6 z 12

2009-03-14 15:33

background image

TRegDataInfo

.

type
TRegDataInfo =

record

RegData: TRegDataType;
DataSize:

Integer

;

end;

Po wywołaniu funkcji GetDataInfo rekord TRegDataInfo zawierać będzie informacje na temat rodzaju wartości
(parametr RegData) oraz rozmiaru wartości (parametr DataSize). W tabeli 6.1 przedstawiono możliwe wartości
parametru RegData.

Tabela 6.1. Możliwa zawartość typu TRegDataType

Nazwa

Opis

rdUnknown

Wartość rejestru nie może zostać zidentyfikowana

rdString

Wartość tekstowa

rdExpandString

Wartość tekstowa z zerowym ogranicznikiem

rdInteger

32-bitowa wartość Integer

rdBinary

Wartość binarna

Przykład użycia:

uses Registry;

procedure TForm1.

FormCreate

(

Sender:

TObject

)

;

var
Reg : TRegistry;
RegInfo : TRegDataInfo;
begin
Reg := TRegistry.

Create

;

try

Reg.

OpenKey

(

'SOFTWARE\b4p'

,

False

)

;

Reg.

GetDataInfo

(

'App Dir'

, RegInfo

)

;

case RegInfo.

RegData

of

rdUnknown:

ShowMessage

(

'Niezidentyfikowana wartość'

)

;

rdString:

ShowMessage

(

'Wartość tekstowa!'

)

;

rdExpandString:

ShowMessage

(

'Wartość tekstowa z zerowym ogranicznikiem'

)

;

rdInteger:

ShowMessage

(

'Wartość Integer'

)

;

rdBinary:

ShowMessage

(

'Wartość binarna'

)

;

end;

finally

Reg.

Free

;

end;

end;

GetDataSize

function

GetDataSize

(

const

ValueName:

String

)

:

Integer

;

Funkcja posiada tylko część możliwości polecenia GetDataType. Zwraca bowiem rozmiar konkretnej wartości
Rejestru, podawany w bajtach.

GetDataType

function

GetDataType

(

const

ValueName:

String

)

: TRegDataType;

Rezultat wykonania tej funkcji zawiera rodzaj wartości Rejestru. Funkcja może zwrócić takie dane, jakie zostały
przedstawione w tabeli 6.1.

GetKeyInfo

function

GetKeyInfo

(

var

Value: TRegKeyInfo

)

:

Boolean

;

Dzięki tej funkcji możesz dowiedzieć się czegoś więcej o konkretnym kluczu. Wszystko to za sprawą rekordu
TRegKeyInfo

.

type
TRegKeyInfo =

record

NumSubKeys:

Integer

;

MaxSubKeyLen:

Integer

;

NumValues:

Integer

;

MaxValueLen:

Integer

;

MaxDataLen:

Integer

;

FileTime: TFileTime;
end;

Rekord dostarcza następujących informacji:

NumSubKeys

? ilość podkluczy w danym kluczu. Wiadomo, że określony klucz Rejestru może posiadać

wiele innych kluczy. Ten parametr dostarcza informacji na ten temat.
NumSubKeyLen

? dany klucz może zawierać wiele podkluczy o określonych długościach. NumSubKeyLen

to długość (w znakach) najdłuższego z podkluczy.
NumValues

? ilość wartości w danym kluczu.

MaxValueLen

? długość (w znakach) najdłuższej wartości z danego klucza.

MaxDataLen

? maksymalna wielkość konkretnej wartości w kluczu (w bajtach).

FileTime

? czas ostatniego dostępu do klucza.

GetKeyNames

Delphi :: Kompendium :: Rozdział 6 - 4programmers.net

http://4programmers.net/Delphi/Kompendium/Rozdzia%C5%82_6

7 z 12

2009-03-14 15:33

background image

procedure

GetKeyNames

(

Strings: TStrings

)

;

Dzięki procedurze GetKeyNames możemy poznać nazwy wszystkich kluczy znajdujących się w danym, otwartym
przez nas kluczu. Wszystkie nazwy zostaną umieszczone w zmiennej typu TStrings. Miałeś już okazję zapoznać
się z klasą TStrings w rozdziale 2. Klasa ta umożliwia dość prosty dostęp do plików tekstowych i, ogólnie, do
tekstu.

Oto przykład:

procedure TForm1.

FormCreate

(

Sender:

TObject

)

;

var
Reg : TRegistry;
KeyNames :

TStringList

;

begin
Reg := TRegistry.

Create

;

KeyNames :=

TStringList

.

Create

;

try

Reg.

OpenKey

(

'Software'

,

False

)

;

Reg.

GetKeyNames

(

KeyNames

)

;

ShowMessage

(

KeyNames

[

0

])

;

finally

Reg.

Free

;

KeyNames.

Free

; // nie zapomnij o zwolnieniu!

end;

end;

Po uruchomieniu programu zmienna KeyNames zawiera nazwy wszystkich kluczy z klucza głównego ? Software.
Ich nazwy można poznać za pomocą nawiasów kwadratowych:

KeyNames

[

0

]

; // odczytaj pierwszy element

GetValueNames

procedure

GetValueNames

(

Strings: TStrings

)

;

Z funkcji GetValueNames korzysta się podobnie jak z GetKeyNames. Jedyna różnica to rezultat wykonania owej
funkcji. W poprzednim przykładzie użycie procedury GetKeyNames spowodowało odczyt wszystkich nazw
kluczy. Procedura GetValueNames powoduje natomiast odczytanie nazw wszystkich wartości znajdujących się w
danym kluczu.

HasSubKeys

function

HasSubKeys:

Boolean

;

Funkcja HasSubKeys zwraca True, jeżeli dany klucz posiada podklucze.

KeyExists

function

KeyExists

(

const

Key:

String

)

:

Boolean

;

Funkcja KeyExists sprawdza, czy dany klucz, określony w parametrze Key, istnieje. Jeżeli nie, funkcja zwraca
wartość False.

LoadKey

function

LoadKey

(

const

Key, FileName:

String

)

:

Boolean

;

Pamiętasz, jak na samym początku rozdziału mówiłem o możliwości wyeksportowania zawartości Rejestru do
pliku *.reg? Dzięki funkcji LoadKey istnieje możliwość wczytania zawartości pliku (określanego poprzez
parametr FileName) i dodania go do klucza określonego poprzez parametr Key.

SaveKey

function

SaveKey

(

const

Key, FileName:

String

)

:

Boolean

;

SaveKey

zapisuje zawartość konkretnego klucza Rejestru w pliku określonym parametrem FileName.

MoveKey

procedure

MoveKey

(

const

OldName, NewName:

String

;

Delete

:

Boolean

)

;

W celu przeniesienia danego klucza do innego możesz skorzystać z funkcji MoveKey. Pierwszy parametr stanowi
dotychczasową ścieżkę klucza; parametr NewName to nowa ścieżka, a ostatni parametr stanowi informację o
tym, czy klucz ma zostać jedynie przeniesiony (True) czy skopiowany (False).

RootKey

Właściwość RootKey (jest to właściwość, a nie metoda!) umożliwia przypisanie wartości klucza głównego,
którego będą dotyczyć operacje:

...

Reg

.

RootKey

:= HKEY_CLASSES_ROOT;

...

Wykonanie powyższego kodu spowoduje, że wszelkie operacje na Rejestrze będą związane z kluczem głównym
? HKEY_CLASSES_ROOT.

Praktyczny przykład

Aby utrwalić wiadomości dotyczące Rejestru, proponuję wykonanie małego ćwiczenia. Program będzie dodawał
odpowiedni klucz do Rejestru Windows, dzięki czemu za każdym uruchomieniem systemu uruchamiany będzie
także nasz program. W tym celu należy dodać odpowiednią wartość do klucza HKEY_CURRENT_USER\SOFTWARE
\Microsoft\Windows\CurrentVersion\Run.

W kluczu tym musi się znaleźć jakaś wartość określająca ścieżkę do naszej aplikacji. Przypominam, że ścieżkę

Delphi :: Kompendium :: Rozdział 6 - 4programmers.net

http://4programmers.net/Delphi/Kompendium/Rozdzia%C5%82_6

8 z 12

2009-03-14 15:33

background image

do aplikacji zwraca funkcja ExeName z klasy TApplication. Nazwa klucza może być dowolna, byleby wartość
wskazywała na ścieżkę.

Utwórz nowy projekt.

1.

Dodaj na formularzu przycisk i zmień jego właściwość Name na btnDelete.

2.

Wygeneruj zdarzenie OnClick przycisku.

3.

Wygeneruj zdarzenie OnCreate formularza.

4.

Na formularzu znajdzie się przycisk, po którego naciśnięciu odpowiedni klucz zostanie usunięty z Rejestru
(jeżeli np. użytkownik nie chce już, aby program był uruchamiany po starcie systemu). Kod źródłowy programu
znajduje się w listingu 6.2.

Listing 6.2. Kod źródłowy modułu

unit MainFrm;

interface

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

type
TMainForm =

class

(

TForm

)

btnDelete: TButton;

procedure FormCreate

(

Sender:

TObject

)

;

procedure btnDeleteClick

(

Sender:

TObject

)

;

private

{ Private declarations }

public

{ Public declarations }

end;

var
MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.

FormCreate

(

Sender:

TObject

)

;

var
Reg : TRegistry;
begin
Reg := TRegistry.

Create

;

try

{ otwarcie klucza }
Reg.

RootKey

:= HKEY_CURRENT_USER;

Reg.

OpenKey

(

'SOFTWARE\Microsoft\Windows\CurrentVersion\Run'

,

False

)

;

if not Reg.

ValueExists

(

'MyApp'

)

then

begin

Reg.

WriteString

(

'MyApp'

, Application.

ExeName

)

;

Application.

MessageBox

(

'Od tej pory program będzie uruchamiany po starcie systemu!'

,

':-)'

, MB_OK + MB_ICONINFORMATION

)

;

end;

finally

Reg.

Free

;

end;

end;

procedure TMainForm.

btnDeleteClick

(

Sender:

TObject

)

;

var
Reg : TRegistry;
begin
Reg := TRegistry.

Create

;

try

{ otwarcie klucza }
Reg.

RootKey

:= HKEY_CURRENT_USER;

Reg.

OpenKey

(

'SOFTWARE\Microsoft\Windows\CurrentVersion\Run'

,

False

)

;

Reg.

DeleteValue

(

'MyApp'

)

;

finally

Reg.

Free

;

end;

end;

end.

Pełny kod źródłowy powyższego programu znajduje się na płycie CD-ROM w katalogu ..listingi/6/Autostart.

Klasa TINIFile

W module IniFiles.pas znajduje się klasa TINIFile, z której będziemy korzystać podczas wykonywania operacji
na plikach INI. Na szczęście nie musisz od nowa uczyć się nazw poleceń, gdyż w większości są one takie same,
jak w przypadku klasy TRegistry. Z tego też powodu nie będę rozpisywał się zbytnio na temat funkcji klasy
TINIFile

.

Tworzenie nowego pliku INI

Rozpoczęcie pracy z plikami INI musi wiązać się z zainicjowaniem klasy TINIFile (wywołaniem konstruktora).
Konstruktor tej klasy wymaga jednego parametru ? ścieżki do pliku INI. Nie musisz przejmować się tym, że np.
ów plik INI nie istnieje ? w razie potrzeby zostanie stworzony przez Delphi.

uses INIFiles;

procedure TForm1.

Button1Click

(

Sender:

TObject

)

;

var
INI : TIniFile;
begin
INI := TINIFile.

Create

(

'C:\moj.ini'

)

;

try

Delphi :: Kompendium :: Rozdział 6 - 4programmers.net

http://4programmers.net/Delphi/Kompendium/Rozdzia%C5%82_6

9 z 12

2009-03-14 15:33

background image

finally

INI.

Free

;

end;

end;

Powyższy kod spowoduje zainicjowanie klasy TINIFile. W parametrze podałem ścieżkę do nieistniejącego pliku
C:\moj.ini. Wykonanie takiego kodu nie spowoduje jednak utworzenia nowego pliku, gdyż nie zostaną
znalezione funkcje zapisujące coś w pliku INI.

Podczas wywoływania konstruktora klasy TINIFile należy podać pełną ścieżkę do pliku. W
przeciwnym wypadku system utworzy plik w katalogu Windows.

Zapisywanie danych

Jak mówiłem wcześniej, użycie metod z klasy TINIFile jest bardzo podobne do zasad obowiązujących w klasie
TRegistry

, a nazwy metod są wręcz identyczne. Różnica dotyczy za to liczby parametrów. Przypominam, że

pliki INI dodatkowo składają się z sekcji, tak więc podczas każdej operacji na tych plikach (zapis, odczyt)
należy podać także nazwę sekcji (w pierwszym parametrze).

uses INIFiles;

procedure TForm1.

Button1Click

(

Sender:

TObject

)

;

var
INI : TIniFile;
begin
INI := TINIFile.

Create

(

'C:\moj.ini'

)

;

try

INI.

WriteString

(

'Main'

,

'Klucz'

,

'Wartość'

)

;

finally

INI.

Free

;

end;

end;

Wykonanie powyższego kodu spowoduje utworzenie nowej sekcji ? Main (jeżeli oczywiście dana sekcja nie
istnieje), a w niej klucza o nazwie Klucz z wartością Wartość. Teraz jeżeli plik C:\moj.ini nie istnieje, zostanie
utworzony, a jego zawartość będzie się przedstawiać tak:

[Main]

Klucz=Wartość

Odczyt danych

Funkcje odczytujące dane z pliku INI także zawierają po trzy parametry ? przykładowa deklaracja funkcji
ReadString wygląda tak:

function ReadString

(

const Section, Ident, Default:

String

)

:

String

;

override;

Pierwszy parametr stanowi nazwę sekcji, drugi ? nazwę klucza, a trzeci ? dla odmiany ? wartość domyślną.
Wartość domyślna stosowana jest na wypadek, gdyby dany plik INI nie istniał lub dany klucz (lub sekcja) nie
znajdował się w tym pliku. Wówczas funkcja ReadString zwraca wartość określoną w trzecim parametrze.

uses INIFiles;

procedure TForm1.

Button1Click

(

Sender:

TObject

)

;

var
INI : TIniFile;
begin
INI := TINIFile.

Create

(

'C:\moj.ini'

)

;

try

ShowMessage

(

INI.

ReadString

(

'Main'

,

'Klucz'

,

'Wartość'

)

)

;

finally

INI.

Free

;

end;

end;

Funkcje związane z operacjami na sekcjach

Jak wspominałem na początku, pliki INI są podzielone na sekcje. W tym podpunkcie zajmiemy się omawianiem
funkcji, których brakuje w klasie TRegistry ? czyli funkcji, które operują na sekcjach plików INI.
Podstawowe funkcje to: ReadSection, ReadSections, ReadSectionValues oraz EraseSection.

ReadSection

procedure ReadSection

(

const Section:

String

; Strings: TStrings

)

;

override;

Procedura ReadSection odczytuje wszystkie klucze znajdujące się w danej sekcji. Pierwszy parametr musi być
nazwą sekcji, a kolejny ? wskazaniem na zmienną typu TStrings.

procedure TForm1.

Button1Click

(

Sender:

TObject

)

;

var
INI : TINIFile;
Keys :

TStringList

;

begin
INI := TINIFile.

Create

(

'C:\moj.ini'

)

;

Keys :=

TStringList

.

Create

;

try

INI.

ReadSection

(

'Main'

, Keys

)

;

{ Zmienna Keys zawiera teraz nazwy wszystkich kluczy w sekcji }

finally

Keys.

Free

;

Delphi :: Kompendium :: Rozdział 6 - 4programmers.net

http://4programmers.net/Delphi/Kompendium/Rozdzia%C5%82_6

10 z 12

2009-03-14 15:33

background image

INI.

Free

;

end;

end;

ReadSections

procedure ReadSections

(

Strings: TStrings

)

;

virtual; abstract;

Czasem zachodzi potrzeba odczytu wszystkich sekcji znajdujących się w pliku INI. Wówczas z pomocą
przychodzi procedura ReadSections. Procedura ta wczytuje do parametru Strings wszystkie nazwy sekcji z
danego pliku INI. Korzystanie z niej jest podobne do przypadku ReadSection.

ReadSectionValues

procedure ReadSectionValues

(

const Section:

String

; Strings: TStrings

)

;

override;

Chcąc odczytać wartości znajdujące się w danej sekcji, należy skorzystać z procedury ReadSectionValues.
Pierwszy parametr musi być nazwą sekcji, a drugi wskazaniem na zmienną typu TStrings. Po uruchomieniu
programu do parametru Strings przypisane zostaną nazwy wszystkich kluczy oraz wartości z danej sekcji.
Klucze są połączone z wartościami znakiem =, więc pozostaje jeszcze sprawa oddzielenia tych dwóch pozycji.

Klasa TStrings posiada przydatne właściwości, które pomogą Ci rozdzielić klucz od wartości. Przede wszystkim
jest to właściwość NameValueSeparator. Nadanie jej wartości ?=? spowoduje oddzielenie klucza od wartości i
przypisanie ich do odpowiednich właściwości: Names oraz Values. Do konkretnej wartości należy odwołać się za
pomocą nawiasów kwadratowych.

EraseSection

procedure EraseSection

(

const Section:

String

)

;

override;

Skoro istnieją funkcje służące do odczytywania zawartości sekcji, to musi istnieć także procedura usuwająca
całe sekcje. Do takich funkcji należy EraseSection. Wystarczy w parametrze Section podać nazwę sekcji, aby
wszystkie klucze w niej się znajdujące zostały skasowane.

Przykładowy program

Abyś mógł utrwalić nieco wiadomości na temat plików INI, pragnę zaprezentować Ci prostą aplikację działającą
na plikach INI. Program będzie realizował logowanie. Po uruchomieniu zostanie wyświetlone małe okienko, w
którym użytkownik powinien wpisać swój pseudonim. Po kolejnym uruchomieniu programu użytkownik zostanie
wykryty (rysunek 6.5).

Rysunek 6.5. Etykieta powitalna

Cały program składa się praktycznie z jednej tylko procedury (zdarzenia) OnCreate:

procedure TMainForm.

FormCreate

(

Sender:

TObject

)

;

var
INI : TINIFile;
Login :

String

; // login wczytany z pliku INI

begin
{ na samym początku należy sprawdzić, czy plik jest utworzony }

if not

FileExists

(

ExtractFilePath

(

Application.

ExeName

)

+

'setup.ini'

)

then

begin

{ jeżeli nie można znaleźć pliku, wyświetl okienko z prośbą o
wpisanie swojego loginu }
Login :=

InputBox

(

'Rejestracja...'

,

'Podaj login'

,

''

)

;

if Login <>

''

then // sprawdź, czy login nie jest pusty

begin

{ jeżeli tak nie jest ? utwórz plik }
INI := TINIFile.

Create

(

ExtractFilePath

(

Application.

ExeName

)

+

'setup.ini'

)

;

try

INI.

WriteString

(

'Main'

,

'Login'

, Login

)

; // zapisz do pliku login

lblMain.

Caption

:=

'Witaj '

+ Login;

finally

INI.

Free

;

end;

Exit

; // nie rób już nic...

end else Application.

Terminate

; // jeżeli użytkownik nie wpisał loginu ? zakończ aplikacje

end;

{ ten kod zostanie wykonany tylko wtedy, gdy plik INI został znaleziony }
INI := TINIFile.

Create

(

ExtractFilePath

(

Application.

ExeName

)

+

'setup.ini'

)

;

try

Login := INI.

ReadString

(

'Main'

,

'Login'

,

'Adam Boduch'

)

; // następuje odczyt loginu

lblMain.

Caption

:=

'Witaj '

+ Login; // następnie wyświetl login na komponencie

finally

INI.

Free

;

end;

end;

Na samym początku program sprawdza, czy w katalogu znajduje się plik setup.ini. Jeżeli tak, sprawa jest
prosta: należy odczytać wartość klucza z pliku INI i wyświetlić ją w etykiecie. Jeżeli natomiast plik nie istnieje,
należy wyświetlić okienko, w którym użytkownik będzie mógł podać swój pseudonim. Korzystamy w tym
momencie z funkcji InputBox, która znajduje się w module Dialogs.pas (rysunek 6.6). Przy wywoływaniu

Delphi :: Kompendium :: Rozdział 6 - 4programmers.net

http://4programmers.net/Delphi/Kompendium/Rozdzia%C5%82_6

11 z 12

2009-03-14 15:33

background image

« Obsługa komunikatów

Spis treści

Obsługa plików »

polecenia InputBox należy podać trzy parametry typu String. Pierwszy to napis na pasku tytułowym okienka,
drugi to tekst etykiety, natomiast ostatni parametr to domyślna wartość w polu typu TEdit.

Rysunek 6.6. Okienko wywoływane za pośrednictwem funkcji InputBox

Podsumowanie

Jestem przekonany, że tworząc bardziej zaawansowane programy, będziesz zmuszony do korzystania z plików
INI lub z Rejestru. Nie jest to w sumie takie trudne, a pozwala na efektywne przechowywanie (zachowanie)
ustawień programu.

Po przeczytaniu tego rozdziału powinieneś mieć już jakąś wiedzę na temat Rejestru czy plików INI ? w razie
czego zawsze możesz sięgnąć po ten podręcznik i odświeżyć sobie pamięć.

Załączniki:

Listingi_6.zip

(212.51 kB)

Więcej informacji

Delphi 2005. Kompendium
programisty

Adam Boduch

Format: B5, stron: 1048
oprawa twarda
Zawiera CD-ROM

©

Helion 2003. Autor:

Adam Boduch

. Zabrania się rozpowszechniania tego tekstu bez zgody autora.

Kategoria

:

Kompendium

Ostatnia modyfikacja

05-02-2006 14:36

Ostatni autor

Adam Boduch

Ilość wyświetleń

20253

Wersja

1

rfl2

dnia 20-09-2007 13:35

Nie bardzo zajarzyłem odczytywanie wartości z poszczególnych kluczy w pliku INI. Chce odczytać te
wartości, wpisuje INI.ReadSectionValues('Sekcja',Key.NameValueSeparator) i w ShowMessage
wyskakuje mi "="

Marooned

dnia 02-03-2006 18:27

Chciałbym przestrzec nowych programistów przed tym, co widać na rysunku

http://4programmers.net

/text/Image:6.2.jpg

i następnych (oraz w kodach źródłowych powiązanych z tym zagadnieniem)

Jest tam stworzony klucz bezpośrednio w HKCU co absolutnie NIE jest dobrym pomysłem. Istnieją
pewne niepisane standardy i należy się ich trzymać, aby zachować jako taki porządek w rejestrze.

Klucze dla swoich programów należy tworzyć w jednej z dwóch lokacji poniżej:
HKEY_CURRENT_USER\Software\NaszaNazwa
HKEY_LOCAL_MACHINE\Software\NaszaNazwa

Do HKCU mamy dostęp z konta danego użytkownika, do HKLM z konta dowolnego użytkownika, więc
wybór miejsca docelowego zależy od tego, czy instalujemy program dla wybranego konta czy dla
wszystkich.

Dodaj komentarz

Delphi :: Kompendium :: Rozdział 6 - 4programmers.net

http://4programmers.net/Delphi/Kompendium/Rozdzia%C5%82_6

12 z 12

2009-03-14 15:33


Wyszukiwarka

Podobne podstrony:
Delphi Kompendium Roz6
Delphi Kompendium Roz8
Delphi Kompendium Roz10
Delphi Kompendium Roz12
Delphi Kompendium Roz5
Delphi Kompendium Roz14
Delphi 7 Kompendium programisty
Delphi 7 Kompendium programisty del7ko 2
Delphi 7 Kompendium programisty
Delphi Kompendium programisty 2
Delphi Kompendium Roz5
Delphi 7 Kompendium programisty
Delphi 7 Kompendium programisty 2
Delphi Kompendium programisty
Delphi Kompendium Roz12
Delphi Kompendium programisty 2
Delphi 7 Kompendium programisty del7ko
Delphi Kompendium programisty delpbb

więcej podobnych podstron