Delphi — это среда быстрой разработки, в которой в качестве языка программирования используется язык Delphi. Язык Delphi — строго типизированный объектно-ориентированный язык, в основе которого лежит хорошо знакомый программистам Object Pascal.

На сегодняшний день позволяет разрабатывать ПО для Microsoft Windows, Mac OS, iOS и Android и входит в состав  Embarcadero RAD Studio.

Автор: Алексей Федоров

Реестр - это центральное хранилище информации о параметрах системы и установленных программах. В версиях Windows до Windows 95 программисты сохраняли параметры программ либо в INI-файлах WIN.INI и SYSTEM.INI, либо в дополнительных INI-файлах. Хотя использование INI-файлов поддерживается и в Win32, Microsoft настоятельно рекомендует для хранения необходимых в работе программы параметров пользоваться реестром. Реестр представляет собой иерархическую базу данных, cостоящую из секций, подсекций и элементов. Каждая секция имеет свое назначение. Хранить данные о пользовательских программах Microsoft рекомендует в секции HKEY_CURRENT_USER и подсекции Software. В этой подсекции вы создаете подсекцию, идентифицирующую вашу программу или фирму, и уже внутри нее располагаете данные.

Модуль Registry

Для упрощения работы с регистратором в состав Delphi (начиная с версии 2.0) входит модуль REGISTRY, содержащий реализацию трех классов, - TRegistry, TRegistryIniFile и TRegIniFile.

Внимание! Чтобы использовать свойства и методы классов TRegistry, TRegistryIniFile и TRegIniFile, необходимо включить в список uses модуль Registry.


TRegIniFile

Собственно говоря, задача класса TRegIniFile - упростить перенос 16-битных программ в среду Windows 95. Методы этого класса эквивалентны методам класса TIniFile в 16-битной версии Delphi. Класс TRegIniFile позволяет обращаться к секции HKEY_CURRENT_USER, считывать и записывать строки (методы ReadString и WriteString), целочисленные значения (методы ReadInteger и WriteInteger), логические значения (методы ReadBool и WriteBool), секции (методы ReadSection, ReadSections и ReadSectionValues), удалять секции (метод EraseSection) и элементы (метод DeleteKey). Рассмотрим на примерах, как используются функции этого класса.

Microsoft рекомендует записывать данные, относящиеся к вашей программе, в подсекции секции HKEY_CURRENT_USER_Software. Предположим (не особенно фантазируя на эту тему), что ваша программа называется RegDemo, и данные для нее располагаются в секции Software\RegDemo. Ниже мы покажем, как поместить в регистратор строчные, целочисленные и логические данные, а затем считать их, - этих операций будет достаточно для того, чтобы сохранить в регистраторе параметры нашей программы, а затем считать их.

Прежде чем записать данные в определенную секцию, ее необходимо создать. Это происходит при вызове конструктора объекта TRegIniFile. В качестве параметра вы указываете название секции, и если таковой не существует, она создается:

RegFile := TRegIniFile.Create(SubKey);

После того как файл регистратора открыт (и создана определенная секция), мы можем записать данные. Поддерживаются три типа данных: целочисленные, логические и строчные данные. Для записи этих данных существуют методы WriteInteger, WriteBool и WriteString. В качестве параметров указываются:

· название подсекции;
· название элемента;
· записываемые данные.

Так, чтобы записать значение элемента MyIntVal в подсекции IntKey, следует выполнить код

RegFile.WriteInteger(IntKey, 'Int_Val', 32000);

а для того чтобы прочесть значение, необходимо вызвать метод ReadInteger (в качестве параметров указываются название подсекции, название элемента и значение по умолчанию):

 

RegFile.ReadInteger(IntKey, 'Int_Val', 0));

Для чтения логических и строчных данных используются соответственно методы ReadBool и ReadStr, а для их записи методы WriteBool и WriteString.

Расссмотрим пример использования перечисленных выше методов класса TRegIniFile. Расположим в форме компонент Memo, две группы GroupBox и шесть кнопок три в группе Write и три в группе Read. Нажатие каждой кнопки в группе Write приведет к записи соответствующего значения в реестр, нажатие каждой кнопки в группе Read к чтению этого значения.

clip0011

 


Ниже приведен исходный текст модуля, в котором содержатся обработчики нажатия кнопок, использующие методы класса TRegIniFile.

Code:

unit RDUnit;

interfaceuses

Windows, Messages, SysUtils, Classes, Graphics, Controls,

 

Forms, Dialogs, StdCtrls, Registry;

type

TForm1 = class(TForm)

   Memo1: TMemo;

   GroupBox1: TGroupBox;

   GroupBox2: TGroupBox;

   Label1: TLabel;

   Button1: TButton;

   Button2: TButton;

   Button3: TButton;

   Button4: TButton;

   Button5: TButton;

   Button6: TButton;

   procedure FormCreate(Sender: TObject);

   procedure Button1Click(Sender: TObject);

   procedure Button2Click(Sender: TObject);

   procedure Button3Click(Sender: TObject);

   procedure Button4Click(Sender: TObject);

   procedure Button5Click(Sender: TObject);

   procedure Button6Click(Sender: TObject);

   procedure FormClose(Sender: TObject;

     var Action: TCloseAction);

private

   { Private declarations }

public

   { Public declarations }

end;

var

Form1: TForm1;

implementation{$R *.DFM}var

RegFile: TRegIniFile;

const

//Подсекция

SubKey: string = 'Software\RegDemo';

// Элемент для хранения логических данных

BoolKey: string = 'BoolKey';

// Элемент для хранения целочисленных данных

IntKey: string = 'IntKey';

// Элемент для хранения строчных данных

StrKey: string = 'StrKey';

 

procedure TForm1.FormCreate(Sender: TObject);

begin

// Создать экземпляр класса

RegFile := TRegIniFile.Create(SubKey);

end;

 

procedure TForm1.Button1Click(Sender: TObject);

begin

// Записать целочисленное значение

RegFile.WriteInteger(IntKey, 'Value', 1998);

end;

 

procedure TForm1.Button2Click(Sender: TObject);

begin

// Записать булево значение

RegFile.WriteBool(BoolKey, 'Value', True);

end;

 

procedure TForm1.Button3Click(Sender: TObject);

begin

// Записать строку

RegFile.WriteString(StrKey, 'Value', 'Demo');

end;

 

procedure TForm1.Button4Click(Sender: TObject);

begin

// Считать целочисленное значение

Memo1.Lines.Add('Int Value = ' +

   IntToStr(RegFile.ReadInteger(IntKey,

   'Value', 0)));

end;

 

procedure TForm1.Button5Click(Sender: TObject);

begin

// Считать булево значение

if RegFile.ReadBool(BoolKey, 'Value', False) then

   Memo1.Lines.Add('Bool Value = True')

else

   Memo1.Lines.Add('Bool Value = False');

end;

 

procedure TForm1.Button6Click(Sender: TObject);

begin

// Считать строку

Memo1.Lines.Add(RegFile.ReadString(StrKey, 'Value', ''));

end;

 

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

begin

// Удалить секцию

RegFile.EraseSection(SubKey);

// Освободить память

RegFile.Free;

end;

end.

 

 


На приведенном ниже рисунке показано, как выглядит созданная нами подсекция в редакторе REGEDIT.

clip0012

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

Класс TRegistry

Прежде чем рассмотреть пример использования свойств и методов класса TRegistry, давайте кратко перечислим их.

В следующей таблице перечислены свойства класса TRegistry.

Свойство

Описание

CurrentKey

Позволяет узнать текущую подсекцию, в которой проводятся операции по чтению и записи. Для изменения подсекции следует использовать методы OpenKey и OpenKeyReadOnly

CurrentPath

Позволяет узнать полное название текущей подсекции

LazyWrite

Задает способ обновления информации в реестре непосредственно или после вызова метода CloseKey.

RootKey

Задает корневую секцию в реестре. По умолчанию установлено значение HKEY_CURRENT_USER

В следующей таблице перечислены методы класса TRegistry.

Метод

Описание

CloseKey

Записывает внесенные изменения и закрывает текущую подсекцию

Create

Создает экземпляр класса TRegistry и задает значение корневой секции - HKEY_CURRENT_USER

CreateKey

Создает подсекцию

DeleteKey

Удаляет подсекцию

DeleteValue

Удаляет значение элемента

Destroy

Уничтожает ранее созданный экземпляр класса TRegistry

GetDataInfo

Возвращает тип данных для указанного элемента

GetDataSize

Возвращает размер данных для указанного элемента

GetDataType

Возвращает тип данных для указанного элемента

GetKeyInfo

Возвращает информацию о текущем элементе

GetKeyNames

Возвращает имена подсекций для указанной секции

GetValueNames

Возвращает названия элементов для указанной подсекции

HasSubKeys

Позволяет узнать, имеются ли подсекции для указанной секции

KeyExists

Позволяет узнать, существует ли элемент

LoadKey

Создает новую подсекцию и загружает в нее информацию из указанного файла

MoveKey

Перемещает указанную подсекцию и все вложенные подсекции в заданное место

OpenKey

Открывает подсекцию

OpenKeyReadOnly

Открывает подсекцию только для чтения

ReadBinaryData

Считывает данные в бинарном формате

ReadBool

Считывает данные в булевом формате

ReadCurrency

Считывает данные в формате валюты

ReadDate

Считывает данные в формате даты

ReadDateTime

Считывает данные в формате “дата/время”

ReadFloat

Считывает данные в формате с плавающей точкой

ReadInteger

Считывает данные в целочисленном формате

ReadString

Считывает данные в строчном формате

ReadTime

Считывает данные в формате времени

RegistryConnect

Устанавливает соединение с реестром на другом компьютере

RenameValue

Переименовывает элемент

ReplaceKey

Замещает значение элемента значениями из файла

RestoreKey

Восстанавливает значение элемента из файла

SaveKey

Сохраняет значение элемента в файле

UnLoadKey

Удаляет подсекцию, загруженную методом LoadKey

ValueExists

Позволяет узнать, существует ли значение у элемента

WriteBinaryData

Записывает данные в бинарном формате

WriteBool

Записывает данные в булевом формате

WriteCurrency

Записывает данные в формате валюты

WriteDate

Записывает данные в формате даты

WriteDateTime

Записывает данные в формате “дата/время”

WriteExpandString

Записывает данные в формате "расширенно" строки

WriteFloat

Записывает данные в формате с плавающей точкой

WriteInteger

Записывает данные в целочисленном формате

WriteString

Записывает данные в строчном формате

WriteTime

Записывает данные в формате времени

 


После того как мы кратко познакомились со свойствами и методами класса TRegistry, давайте рассмотрим несколько примеров их использования.

 

Инициализация

 

Перед использованием свойств и методов класса TRegistry, необходимо создать экземпляр этого класса. Например:

 

Code:

var

R: TRegistry;

...R := TRegistry.Create;

  

Задание корневой секции

Если вы собираетесь работать с секцией, отличной от HKEY_CURRENT_USER (это значение задается по умолчанию), то после инициализации вы должны изменить значение свойства RootKey. Возможны следующие значения:

 

Code:

HKEY_CLASSES_ROOT

HKEY_CURRENT_USER

HKEY_LOCAL_MACHINE

HKEY_USERS

HKEY_PERFORMANCE_DATA

HKEY_CURRENT_CONFIG

HKEY_DYN_DATA

 

 Например:

Code:

with R do

begin

RootKey := HKEY_LOCAL_MACHINE;

//

// Продолжаем работу с реестром

//

end;

 

В Windows нет разделения каналов записи по источникам.

 

CD-ROM ----------|

                |             |--- Динамики

Микрофон --------|             |

                |-- Windows --|--- Записывающие программы

Линейный вход ---|             |

                |             |--- Линейный выход

MIDI ------------|

 

Все поступающие в систему звуки смешиваются, и лишь после этого их получает программа.

Для получения звукового сигнала нужно воспользоваться WinAPI.

WaveInOpen открывает доступ к микрофону.

Одновременно только одна программа может работать с микрофоном.

Заодно Вы указываете, какая нужна частота, сколько бит на значение и размер буфера.

От последнего зависит, как часто и в каком объеме информация будет поступать в программу.

 

 

Далее нужно выделить память для буфера и вызвать функцию WaveInAddBuffer,

которая передаст Windows пустой буфер.

После вызова WaveInStart Windows начнет заполнять буфер,

и, после его заполнения, пошлет сообщение MM_WIM_DATA.

В нем нужно обработать полученную информацию и вновь вызвать WaveInAddBuffer,

тем самым указав, что буфер пуст.

 

Функции WaveInReset и WaveInClose прекратят поступление информации в программу и закроют доступ к микрофону.

 

 

Эта программа считывает сигнал с микрофона и выводит его на экран.

Частота сигнала - 22050 Гц. Количество бит определяется флажком, размер буфера TrackBar-ом.


Code:

unit Unit1;

 

interface

 

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls, ExtCtrls, ComCtrls, MMSystem;

 

type

TData8 = array [0..127] of byte;

PData8 = ^TData8;

TData16 = array [0..127] of smallint;

PData16 = ^TData16;

TPointArr = array [0..127] of TPoint;

PPointArr = ^TPointArr;

TForm1 = class(TForm)

   Button1: TButton;

   Button2: TButton;

   PaintBox1: TPaintBox;

   TrackBar1: TTrackBar;

   CheckBox1: TCheckBox;

   procedure Button1Click(Sender: TObject);

   procedure Button2Click(Sender: TObject);

   procedure FormDestroy(Sender: TObject);

   procedure CheckBox1Click(Sender: TObject);

   procedure FormCreate(Sender: TObject);

private

   { Private declarations }

public

   procedure OnWaveIn(var Msg: TMessage); message MM_WIM_DATA;

end;

 

var

Form1: TForm1;

 

implementation

 

{$R *.DFM}

 

var

WaveIn: hWaveIn;

hBuf: THandle;

BufHead: TWaveHdr;

bufsize: integer;

Bits16: boolean;

p: PPointArr;

stop: boolean = false;

 

procedure TForm1.Button1Click(Sender: TObject);

var

header: TWaveFormatEx;

BufLen: word;

buf: pointer;

begin

BufSize := TrackBar1.Position * 500 + 100; { Размер буфера }

Bits16 := CheckBox1.Checked;

with header do begin

   wFormatTag := WAVE_FORMAT_PCM;

   nChannels := 1{ количество каналов }

   nSamplesPerSec := 22050; { частота }

   wBitsPerSample := integer(Bits16) * 8 + 8; { 8 / 16 бит }

   nBlockAlign := nChannels * (wBitsPerSample div 8);

   nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;

   cbSize := 0;

end;

WaveInOpen(Addr(WaveIn), WAVE_MAPPER, addr(header),

   Form1.Handle, 0, CALLBACK_WINDOW);

BufLen := header.nBlockAlign * BufSize;

hBuf := GlobalAlloc(GMEM_MOVEABLE and GMEM_SHARE, BufLen);

Buf := GlobalLock(hBuf);

with BufHead do begin

   lpData := Buf;

   dwBufferLength := BufLen;

   dwFlags := WHDR_BEGINLOOP;

end;

WaveInPrepareHeader(WaveIn, Addr(BufHead), sizeof(BufHead));

WaveInAddBuffer(WaveIn, addr(BufHead), sizeof(BufHead));

GetMem(p, BufSize * sizeof(TPoint));

stop := true;

WaveInStart(WaveIn);

end;

 

procedure TForm1.Button2Click(Sender: TObject);

begin

if stop = false then Exit;

stop := false;

while not stop do Application.ProcessMessages;

stop := false;

WaveInReset(WaveIn);

WaveInUnPrepareHeader(WaveIn, addr(BufHead), sizeof(BufHead));

WaveInClose(WaveIn);

GlobalUnlock(hBuf);

GlobalFree(hBuf);

FreeMem(p, BufSize * sizeof(TPoint));

end;

 

procedure TForm1.OnWaveIn;

var

i: integer;

data8: PData8;

data16: PData16;

h: integer;

XScale, YScale: single;

begin

h := PaintBox1.Height;

XScale := PaintBox1.Width / BufSize;

if Bits16 then begin

   data16 := PData16(PWaveHdr(Msg.lParam)^.lpData);

   YScale := h / (1 shl 16);

   for i := 0 to BufSize - 1 do

     p^[i] := Point(round(i * XScale),

       round(h / 2 - data16^[i] * YScale));

end else begin

   Data8 := PData8(PWaveHdr(Msg.lParam)^.lpData);

   YScale := h / (1 shl 8);

   for i := 0 to BufSize - 1 do

     p^[i] := Point(round(i * XScale),

       round(h - data8^[i] * YScale));

end;

with PaintBox1.Canvas do begin

   Brush.Color := clWhite;

   FillRect(ClipRect);

   Polyline(Slice(p^, BufSize));

end;

if stop

   then WaveInAddBuffer(WaveIn, PWaveHdr(Msg.lParam),

     SizeOf(TWaveHdr))

   else stop := true;

end;

 

procedure TForm1.FormDestroy(Sender: TObject);

begin

Button2.Click;

end;

 

procedure TForm1.CheckBox1Click(Sender: TObject);

begin

if stop then begin

   Button2.Click;

   Button1.Click;

end;

end;

 

procedure TForm1.FormCreate(Sender: TObject);

begin

TrackBar1.OnChange := CheckBox1Click;

Button1.Caption := 'Start';

Button2.Caption := 'Stop';

CheckBox1.Caption := '16 / 8 bit';

end;

 

end.

 

 

 

Даниил Карапетян.

 

Все потомки TComponent могут посылать сообщения CM_MOUSEENTER и CM_MOUSELEAVE во время вхождения и покидания курсора мыши области компонента. Если вам необходимо, чтобы ваши компоненты обладали реакцией на эти события, необходио написать для них соответствующие обработчики.

Code:

procedure CMMouseEnter(var msg:TMessage); message CM_MOUSEENTER;

procedure CMMouseLeave(var msg: TMessage); message CM_MOUSELEAVE;

..

..

..

procedure MyComponent.CMMouseEnter(var msg:TMessage);

begin

 

inherited;

{действия на вход мыши в область компонента}

end;

 

procedure MyComponent.CMMouseLeave(var msg: TMessage);

begin

 

inherited;

{действия на покидание мыши области компонента}

end;

 

 

 

 

Дополнение

 

Часто приходится сталкиваться с ситуацией, когда необходимо обработать два важных события для визуальных компонентов:

 

MouseEnter - когда событие мыши входит в пределы визуального компонента;

MouseLeave - когда событие мыши оставляет его пределы.

Известно, что все Delphi объявляет эти сообщения в виде:

Cm_MouseEnter;

Cm_MouseLeave.

Т.е. все визуальные компоненты, которые порождены от TControl, могут отлавливать эти события. Следующий пример показывает как создать наследника от TLabel и добавить два необходимых события OnMouseLeave и OnMouseEnter.

 

Code:

(*///////////////////////////////////////////////////////*)

(*// Author: Briculski Serge

(*// E-Mail: Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.

(*// Date: 26 Apr 2000

(*///////////////////////////////////////////////////////*)

 

unit BS_Label;

 

interface

 

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

StdCtrls;

 

type

TBS_Label = class(TLabel)

private

   { Private declarations }

   FOnMouseLeave: TNotifyEvent;

   FOnMouseEnter: TNotifyEvent;

   procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;

   procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;

protected

   { Protected declarations }

public

   { Public declarations }

published

   { Published declarations }

   property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;

   property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;

end;

 

procedure Register;

 

implementation

 

procedure Register;

begin

RegisterComponents('Custom', [TBS_Label]);

end;

 

{ TBS_Label }

 

procedure TBS_Label.CMMouseEnter(var Message: TMessage);

begin

if Assigned(FOnMouseEnter) then

   FOnMouseEnter(Self);

end;

 

procedure TBS_Label.CMMouseLeave(var Message: TMessage);

begin

if Assigned(FOnMouseLeave) then

   FOnMouseLeave(Self);

end;

 

end.