Технология без интересного имени или как работать со сканером

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

Автор: Павел

В настоящее время в конференциях то и дело встречаются вопросы типа: как мне получить изображение со сканера, с web камеры и т.д.. При том, что и интернете практически полностью отсутствуют материалы по этим вопросам на русском языке и при достаточном разнообразии их на английском. Эта статья должна помочь начинающему программисту на Delphi разобраться в них. В статье подробно, с примерами описана работа со сканером с использованием популярной библиотеки Easy TWAIN.

Введение

В отличие от принтеров сканеры изначально не поддерживались ОС Windows и не имеют API для работы с ними. В начале своего появления сканеры взаимодействовали с программами посредством уникального для каждой модели сканера интерфейса, что серьезно затрудняло включение поддержки работы со сканером в прикладные программы.

Для решения этой проблемы был разработан TWAIN — индустриальный стандарт интерфейса программного обеспечения для передачи изображений из различных устройств в Windows и Macintosh. Стандарт издан и поддерживается TWAIN рабочей группой — официальный сайт www.twain.org. Стандарт издан в 1992 г. В настоящее время действует версия 1.9 от января 2000 г. Абревеатура TWAIN изначально не имела какого-то определенного смысла хотя позже была придумана расшифровка: (Technology Without An Interesting Name — Технология без интересного имени). TWAIN — не протокол аппаратного уровня, он требует драйвера (названного Data Source или DS) для каждого устройства.

К настоящему времени (май 2000 г.) TWAIN доступен для Windows 3.1 и выше (Intel и совместимые процессоры), Macintosh и OS/2. Для Linux самый близкий стандарт — SANE.

Менеджер TWAIN (DSM) — действует как координатор между приложениями и Источником Данных (Data Source). DSM имеет минимальный пользовательский интерфейс — только выбор DS. Все взаимодействие с пользователем вне прикладной программы осуществляется по средствам DS.

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

Использование TWAIN

DSM и DS это DLLs загружаемые в адресное пространство приложения и работают как подпрограммы приложения. DSM использует межпроцесcную связь, что бы координировать действия со своими копиями, когда больше чем одна программа использует TWAIN.

Упрощенная схема действия приложения использующего TWAIN:

Открыть диалог настройки соответствующего устройства (диалог отображает DS) и задать соответствующие настройки.

Приложение ожидает сообщение от DS, что изображение готово. Во время ожидания все зарегистрированные сообщения будут направляться через TWAIN. Если это не будет выполняться, то приложение не получит сообщения о готовности изображения.

Приложение принимает изображение от DS.

TWAIN определяет три типа передачи изображения:

Native — в Windows это DIB в памяти

Memory — как блоки пикселей в буферах памяти

File — DS записывает изображение непосредственно в файл (не обязательно поддерживается)

Приложение закрывает DS.

Использование EZTWAIN

Данная библиотека была разработана, что бы упростить разработку программ использующих TWAIN предоставляя разработчику упрощенную версию TWAIN API.

EZTWAN обеспечивает передачу всех windows сообщений через TWAIN и ожидает сообщения о готовности изображения.

Библиотека EZTWAIN является свободно распространяемой библиотекой с открытыми исходными кодами. В настоящее время выпущена версия 1.12. Библиотеку можно свободно скачать с сайта: www.dosadi.com, библиотека написана на C и предназначена для использования как DLL, необходимый для ее использования с Delphi модуль так же можно скачать с сайта. Кроме нее у меня с сайта можно скачать модификацию данной библиотеки, предназначенную для статической компоновки с программой на Delphi. Указанная версия (MultiTWAIN for Delphi) не требует наличия библиотеки EZTW32.DLL.

Структура программы

Используемые функции.

Перед вызовом функций сканирования необходимо вызвать функцию:

TWAIN_SelectImageSource(hwnd: HWND): Integer;

Данная функция позволяет выбрать источник получения данных из списка TWAIN совместимых устройств, в качестве параметра она получает хендл основного окна прикладной программы. Следует заменить, что если в системе имеется одно TWAIN совместимое устройство, то вызывать функцию не обязательно.

Для получения изображения служит функция:

TWAIN_AcquireNative(hwnd: HWND; pixmask: Integer): HBitmap;

где:

hwnd — хендел основного окна прикладной программы (допускается указывать 0);

pixmask — режим сканирования ( необходимо задавать 0 — указание другого режима может приводить к ошибке);

hBitmap — указатель на область памяти, содержащей полученные данные в DIB формате.

По окончании работы с DIB данными их необходимо удалить вызвав процедуру:

TWAIN_FreeNative(hDIB: HBitmap);

где:

hDIB — указатель, полученный при вызове функции TWAIN_AcquireNative.

Для облегчения обработки полученных DIB данных в библиотеке имеется несколько сервисных функций:

TWAIN_DibWidth(hDib: HBitmap): Integer;

// Получает ширину изображения в пикселях

TWAIN_DibHeight(hDib: HBitmap): Integer;

// Получает высоту изображения в пикселях

TWAIN_CreateDibPalette(hdib: HBitmap): Integer;

// Получает цветовую палитру изображения

TWAIN_DrawDibToDC(hDC: HDC;

dx, dy, w, h: Integer;

hDib: HBitmap;

sx, sy: Integer);

// Передает DIB данные в формате совместимым

// с указанным контекстом устройства.

Пример программы

Полный текст примера можно взять отсюда. Мы рассмотрим только функцию получения данных с TWAIN устройства:

procedure TForm1.Accquire1Click(Sender: TObject);

var

dat: hBitMap;

PInfo: PBitMapInfoHeader;

Height, Width: integer;

{Функция возведения 2 в степень s}

function stp2(s: byte): longint;

var

m: longint;

i: byte;

begin

m := 2;

for i := 2 to s do

m := m * 2;

stp2 := m;

end;

begin

{Получаем указатель на графические данные}

dat := TWAIN_AcquireNative(Handle, 0);

if dat 0 then

begin

{Получаем указатель на область памяти содержащей DIB

данные и блокируем область памяти}

PInfo := GlobalLock(dat);

{Анализируем полученные данные}

Height := PInfo.biHeight;

Width := PInfo.biWidth;

{Узнаем размер полученного изображения в сантиметрах}

Wcm.Caption := floatToStrF(100 / PInfo.biXPelsPerMeter * Width, ffNumber, 8,

3)

‘ cm’;

Hcm.Caption := floatToStrF(100 / PInfo.biYPelsPerMeter * Height, ffNumber,

8, 3)

‘ cm’;

{Определяем число цветов в изображении}

Colors.Caption := floatToStrF(stp2(PInfo.biBitCount), ffNumber, 8, 0)

‘ цветов’;

{Разблокируем память}

GlobalUnlock(dat);

{Передаем в битовую матрицу графические данные}

{И устанавливаем перехват ошибок}

try

MyBitMap.Palette := TWAIN_CreateDibPalette(dat);

MyBitMap.Width := Width;

MyBitMap.Height := Height;

TWAIN_DrawDibToDC(MyBitMap.Canvas.Handle, 0, 0, Width, Height, dat, 0, 0);

except

// Обрабатываем наиболее вероятную ошибку связанную

// с не хваткой ресурсов для загрузки изображения

on EOutOFResources do

MessageDlg(‘TBitMap: Нет ресурсов для загрузки изображения!’,

mtError, [mbOk], 0);

end;

{Отображаем графические данные}

Image1.Picture.Graphic := MyBitMap;

{Освобождаем память занятую графическими данными}

TWAIN_FreeNative(dat);

end;

end;

Обработка ошибок необходима, так как объект TBitMap имеет серьезные ограничения на размер создаваемого изображения. При этом производится обработка наиболее вероятной ошибки, в случае возникновения другой ошибки, ее обработка будет передана обработчику по умолчанию. Обработка ошибки в данном случае заключается в выдаче диагностического сообщения, в прикладной программе можно реализовать выполнение любых необходимых действий, например, произвести уменьшение разрешения и повторно подать на загрузку в TBitMap.

Заключение

Приведенный здесь пример тестировался на сканере Umax 2000P с драйвером VistaScan32 V3.52. При получении изображений следует помнить, что максимальный размер блока памяти, который может распределить Windows, составляет 2 Гб и при попытке сканировании страниц формата А4 с высоким разрешением можно превысить этот предел. Кроме того, достаточно простой в обращении объект TBitMap имеет куда более серьезные ограничения на размер загружаемых изображений, что требует непосредственной работы с DIB данными. Но это уже тема для отдельной статьи. Если у Вас появились вопросы или предложения пишите мне: speclab@4unet.ru

{/codecitation}

Сканирование изображений

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

Оформил: DeeCo

Автор: http://www.swissdelphicenter.ch

The setup program for Imaging (tool that ships with Windows > 98) installs the Image

Scan control (OCX) and the 32-bit TWAIN DLLs.

All you have to do is to import this ActiveX control in Delphi and generate a component wrapper:

Import the ActiveX Control «Kodak Image Scan Control»

(Select Component|Import ActiveX Control…)

Now add a TImgScan Component from the Register «ActiveX» to your form.

Change the following Properties in the Object Inspector:

FileType = 3 — BMP_Bitmap

PageOption = 4 — OverwritePages

ScanTo = 2 — FileOnly

{***}

Das Setup Programm fьr Imaging (Ist bei Windows > 98 dabei) installiert das Bild Scanning Control (OCX) und die 32-bit TWAIN DLLs.

Importiere das ActiveX-Control «Steuerung fьr Kodak-Bildscan».

(Im Menь Komponente, «ActiveX importieren» anklicken.)

Dann «Steuerung fьr Kodak-Bildscan…» auswдhlen und den «Installieren…» Button anklicken.

Fьge nun eine «TImgScan» Komponente aus dem Register «ActiveX» auf dem Formular ein.

Дndere im Objektinspektor unter «ImgScan1» folgende Eigenschaften:

FileType = 3 — BMP_Bitmap

PageOption = 4 — OverwritePages

ScanTo = 2 — FileOnly

{***}

procedure TForm1.Button1Click(Sender: TObject);

begin

if imgScan1.ScannerAvailable then

try

imgScan1.Image := ‘c:\Scanner.bmp’;

imgScan1.OpenScanner;

imgScan1.Zoom := 100;

imgScan1.StartScan;

Application.ProcessMessages;

finally

imgScan1.CloseScanner;

{ Show the scanned image in Image1 }

imgScan1.Picture.LoadFromFile(Image1.Image);

end;

end;

{/codecitation}

Экспортировать ветвь реестра

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

Оформил: DeeCo

Автор: http://www.swissdelphicenter.ch

unit RegExpo;

interface

uses

Windows, rRegistry, Classes, SysUtils;

{$I-}

{$LONGSTRINGS ON}

{

Regexpo

Author : Arthur Hoornweg (arthur.hoornweg@email.de)

Version : 1.00, May 1998

O/S : Windows 95, 98, ME, NT, 2000, XP

Delphi 2

Function :

This unit allows you to backup a branch of the registry into a *.REG file,

that is compatible with «regedit».

Double-clicking such a file in the explorer will import it.

Example:

ExportRegistryBranch(HKEY_LOCAL_MACHINE,’SOFTWARE\Borland\Delphi’,’A:\DELPHI.REG’)

(c) 1998 A.M. Hoornweg. All rights reserved.

You may use this software for all purposes, both commercial and

noncommercial, as long as proper credit is given. The sourcecode may be distributed

freely, as long as this copyright is included and no more than a marginal fee is

asked.

Disclaimer:

I accept no responsibility whatsoever for any damages caused by these

routines. Use them at your own risk. If you find any bugs, please let me know.

}

procedure ExportRegistryBranch(Rootsection: Integer; regroot: string;

FileName: string);

implementation

function dblBackSlash(t: string): string;

var

k: longint;

begin

Result := t; {Strings are not allowed to have}

for k := Length(t) downto 1 do {single backslashes}

if Result[k] = ‘\’ then Insert(‘\’, Result, k);

end;

procedure ExportRegistryBranch(rootsection: Integer; Regroot: string;

FileName: string);

var

reg: TRegistry;

f: Textfile;

p: PChar;

procedure ProcessBranch(root: string); {recursive sub-procedure}

var

values, keys: TStringList;

i, j, k: longint;

s, t: string; {longstrings are on the heap, not on the stack!}

begin

Writeln(f); {write blank line}

case rootsection of

HKEY_CLASSES_ROOT: s := ‘HKEY_CLASSES_ROOT’;

HKEY_CURRENT_USER: s := ‘HKEY_CURRENT_USER’;

HKEY_LOCAL_MACHINE: s := ‘HKEY_LOCAL_MACHINE’;

HKEY_USERS: s := ‘HKEY_USERS’;

HKEY_PERFORMANCE_DATA: s := ‘HKEY_PERFORMANCE_DATA’;

HKEY_CURRENT_CONFIG: s := ‘HKEY_CURRENT_CONFIG’;

HKEY_DYN_DATA: s := ‘HKEY_DYN_DATA’;

end;

Writeln(f, ‘[‘ s ‘\’ root ‘]’); {write section name in brackets}

reg.OpenKey(root, False);

try

values := TStringList.Create;

try

keys := TStringList.Create;

try

reg.GetValuenames(values); {get all value names}

reg.GetKeynames(keys); {get all sub-branches}

for i := 0 to values.Count — 1 do {write all the values first}

begin

s := values[i];

t := s; {s=value name}

if s = » then s := ‘@’ {empty means «default value», write as @}

else

s := ‘»‘ s ‘»‘; {else put in quotes}

Write(f, dblbackslash(s) ‘=’); {write the name of the key to the file}

case reg.Getdatatype(t) of {What type of data is it?}

rdString, rdExpandString: {String-type}

Writeln(f, ‘»‘ dblbackslash(reg.ReadString(t) ‘»‘));

rdInteger: {32-bit unsigned long integer}

Writeln(f, ‘dword:’ IntToHex(reg.readinteger(t), 8));

{write an array of hex bytes if data is «binary.» Perform a line feed

after approx. 25 numbers so the line length stays within limits}

rdBinary:

begin

Write(f, ‘hex:’);

j := reg.GetDataSize(t); {determine size}

GetMem(p, j); {Allocate memory}

reg.ReadBinaryData(t, p^, J); {read in the data, treat as pchar}

for k := 0 to j — 1 do

begin

Write(f, IntToHex(Byte(p[k]), 2)); {Write byte as hex}

if k j — 1 then {not yet last byte?}

begin

Write(f, ‘,’); {then write Comma}

if (k > 0) and ((k mod 25) = 0) {line too long?} then

Writeln(f, ‘\’); {then write Backslash lf}

end; {if}

end; {for}

FreeMem(p, j); {free the memory}

Writeln(f); {Linefeed}

end;

else

Writeln(f, ‘»»‘); {write an empty string if datatype illegal/unknown}

end;{case}

end; {for}

finally

reg.CloseKey;

end;

finally

{value names all done, no longer needed}

values.Free;

end;

{Now al values are written, we process all subkeys}

{Perform this process RECURSIVELY…}

for i := 0 to keys.Count — 1 do

ProcessBranch(root ‘\’ keys[i]);

finally

keys.Free; {this branch is ready}

end;

end; { ProcessBranch}

begin

if RegRoot[Length(Regroot)] = ‘\’ then {No trailing backslash}

SetLength(regroot, Length(Regroot) — 1);

Assignfile(f, FileName); {create a text file}

Rewrite(f);

if ioResult 0 then Exit;

Writeln(f, ‘REGEDIT4’); {«magic key» for regedit}

reg := TRegistry.Create;

try

reg.Rootkey := Rootsection;

{Call the function that writes the branch and all subbranches}

ProcessBranch(Regroot);

finally

reg.Free; {ready}

Close(f);

end;

end;

end.

{/codecitation}

Экспорт и импорт из реестра

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

reg-файлы это, как и ожидалось, формат, понимаемый и поддерживаемый сугубо программой regedit.

Командная строка у неё такая:

Импорт в реестр:

regedit RegData.reg

Экспорт из реестра:

regedit /e RegData.reg HKEY_LOCAL_MACHINE\Software\Microsoft\Windows

Если в параметрах встречаются пробелы, их ессно надо заключать в кавычки. Код в Delphi, который экспортирует ветвь реестра может быть например такой:

uses

ShellApi;

procedure TMain.ExportBtnClick(Sender: TObject);

var

FileName, Key: string;

begin

FileName := … //заполнить именем файла (расширение указывать)

Key := … //заполнить именем ключа, типа

//Key := ‘HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion’

if ShellExecute(Handle, ‘open’, ‘regedit.exe’,

PChar(Format(‘/e «%s» «%s»‘, [FileName, Key])),

», SW_SHOWDEFAULT) <= 32

then //если ошибка, то возвращаемый код <=32

RaiseLastWin32Error();

end;

{/codecitation}

Чтение строки из реестра без использования класса TRegistry

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

Автор: Dimka Maslov

WEB-сайт: http://delphibase.endimus.com

{ **** UBPFD *********** by delphibase.endimus.com ****

>> Чтение строки из реестра без использования класса TRegistry

Входные параметры:

RootKey — идентификатор корневого раздела реестра, например

HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE и т.д.

Key — имя раздела реестра,

Name — имя параметра, для чтения параметра «По умолчанию» («Default»),

эта строка должна быть пустой

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

будет Тrue в случае успеха или False в случае ошибки.

В случае успеха функция возвращает значение параметра, или

пустую строку при возникновении ошибки чтения из реестра

Зависимости: Windows

Автор: Dimka Maslov, mainbox@endimus.ru, ICQ:148442121, Санкт-Петербург

Copyright: Dimka Maslov

Дата: 13 мая 2002 г.

***************************************************** }

function RegQueryStr(RootKey: HKEY; Key, Name: string;

Success: PBoolean = nil): string;

var

Handle: HKEY;

Res: LongInt;

DataType, DataSize: DWORD;

begin

if Assigned(Success) then

Success^ := False;

Res := RegOpenKeyEx(RootKey, PChar(Key), 0, KEY_QUERY_VALUE, Handle);

if Res ERROR_SUCCESS then

Exit;

Res := RegQueryValueEx(Handle, PChar(Name), nil, @DataType, nil, @DataSize);

if (Res ERROR_SUCCESS) or (DataType REG_SZ) then

begin

RegCloseKey(Handle);

Exit;

end;

SetString(Result, nil, DataSize — 1);

Res := RegQueryValueEx(Handle, PChar(Name), nil, @DataType,

PByte(@Result[1]), @DataSize);

if Assigned(Success) then

Success^ := Res = ERROR_SUCCESS;

RegCloseKey(Handle);

end;

Пример использования:

procedure TForm1.Button1Click(Sender: TObject);

begin

edit1.Text := RegQueryStr(HKEY_CLASSES_ROOT, ‘AVIFile\shell\open\command’, »);

end;

{/codecitation}

Узнать путь к каталогам Windows

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

Звонок в фирму:

— Что вы предпринимаете для защиты от вирусов?

— Выпускаем одноразовые компьютеры…

uses Registry;

procedure TForm1.Button1Click(Sender: TObject);

var

reg : TRegistry;

ts : TStrings;

i : integer;

begin

reg := TRegistry.Create;

reg.RootKey := HKEY_CURRENT_USER;

reg.LazyWrite := false;

reg.OpenKey(‘Software\Microsoft\Windows\CurrentVersion\Explorer\ShellFolders’, false);

ts := TStringList.Create;

reg.GetValueNames(ts);

for i := 0 to ts.Count -1 do

Memo1.Lines.Add(ts.Strings[i] ‘ = ‘ reg.ReadString(ts.Strings[i]));

ts.Free;

reg.CloseKey;

reg.free;

end;

{/codecitation}

Удобная загрузка местоположения формы

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

Автор: Virtualik

Если вы храните параметры местоположения(Top, Left, Width, Height) формы в реестре, то чтобы не загружать данные из нескольких ключей вы можете их записать в один, и из одного же прочитать 😉

По сути, данные записывается в виде record’а. А как это примерно может выглядеть смотрите в примере.

var

Ini: TRegIniFile;

procedure TForm1.FormCreate(Sender: TObject);

var

Rct: TRect;

begin

Ini := TRegIniFile.Create(‘<Здесь вы пишете путь к вашим настройкам в

реестре > ‘);

// Если есть данные —> загружаем их

if Ini.ReadBinaryData(‘FormPosition’, Rct, SizeOf(TRect)) > 0 then

BoundsRect := Rct;

end;

procedure TReply.FormDestroy(Sender: TObject);

var

Rct: TRect;

begin

// Сохранение данных на выходе

Rct := BoundsRect;

Ini.WriteBinaryData(‘MsgPos’, Rct, SizeOf(TRect));

Ini.Free;

end;

{/codecitation}

Сохранить значение TDateTime в реестре

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

Оформил: DeeCo

Автор: http://www.swissdelphicenter.ch

uses

Registry;

// Write TDateTime to Registry

procedure Reg_WriteDateTime(dwRootKey: DWord; const sKey: string; const sField: string; aDate: TDateTime);

begin

with TRegistry.Create do

try

RootKey := dwRootKey;

if OpenKey(sKey, True) then

begin

try

WriteBinaryData(sField, aDate, SizeOf(aDate));

finally

CloseKey;

end;

end;

finally

Free;

end;

end;

// Read TDateTime from Registry

function Reg_ReadDateTime(dwRootKey: DWord; const sKey: string; const sField: string) : TDateTime;

begin

Result := 0; // default Return value

with TRegistry.Create do

begin

RootKey := dwRootKey;

if OpenKey(sKey, False) then

begin

try

ReadBinaryData(sField, Result, SizeOf(Result));

finally

CloseKey;

end;

end;

Free;

end;

end;

// Example:

// Write DateTimePicker1’s DateTime to Registry

procedure TForm1.Button1Click(Sender: TObject);

begin

Reg_WriteDateTime(HKEY_CURRENT_USER, ‘Software\TestXYZ\’,’DateTime’,DateTimePicker1.DateTime);

end;

// Set DateTimePicker1’s DateTime from Registry

procedure TForm1.Button2Click(Sender: TObject);

var

ATime: TDateTime;

begin

ATime := Reg_ReadDateTime(HKEY_CURRENT_USER, ‘Software\TestXYZ\’,’DateTime’);

if ATime 0 then

DateTimePicker1.DateTime := TDateTime(ATime);

end;

{/codecitation}

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

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

Автор: Олег Кулабухов

Необходимо послать всем окнам сообщение WM_WININICHANGE с указанием полного адреса измененного адреса ключа.

procedure TForm1.Button1Click(Sender: TObject);

begin

SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0,

LongInt(PChar(‘RegistrySection’)));

end;

{/codecitation}

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

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

Автор: VID

WEB-сайт: http://delphibase.endimus.com

{ **** UBPFD *********** by delphibase.endimus.com ****

>> Помещение записи в одну из секций автозапуска реестра

Функция помещает параметр Name и значение параметра Data, в одну из секций

автозапуска, выбранного раздела реестра.

HkeyTarget:THkeyTarget — указываете раздел реестра, в одну из секций

автозапуска которого должна быть помещена запись:

htLocalMachine — раздел HKEY_LOCAL_MACHINE

htCurrentUser — раздел HKEY_CURRENT_USER

SectionTarget:TSectionTarget — указываете одну из секций автозапуска,

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

stRun — секция RUN

stRunOnce — секция RunOnce

stRunOnceEx — секция RunOnceEx

Name:String — имя параметра (например, ‘myApplication’)

Data:String — значение параметра (например, Application.Exename)

Зависимости: windows, registry

Автор: VID, vidsnap@mail.ru, ICQ:132234868, Махачкала

Copyright: VID

Дата: 23 мая 2002 г.

***************************************************** }

type

THKEYTarget = (htLocalMachine, htCurrentUser);

type

TSectionTarget = (stRun, stRunOnce, stRunOnceEx);

function StoreToRunSection(HKEYTarget: THKEYTarget;

SectionTarget: TSectionTarget; Name, Data: string): boolean;

var

Reg: TRegistry;

Section: string;

begin

Result := TRUE;

try

reg := TRegistry.Create;

if HKEYTarget = htLocalMachine then

reg.RootKey := HKEY_LOCAL_MACHINE;

if HKEYTarget = htCurrentUser then

reg.RootKey := HKEY_CURRENT_USER;

if SectionTarget = stRun then

Section := ‘Run’;

if SectionTarget = stRunOnce then

Section := ‘RunOnce’;

if SectionTarget = stRunOnceEx then

Section := ‘RunOnceEx’;

reg.LazyWrite := false;

reg.OpenKey(‘Software\Microsoft\Windows\CurrentVersion\’ Section, false);

reg.WriteString(Name, Data);

reg.CloseKey;

reg.free;

except RESULT := FALSE;

end;

end;

// Пример использования:

begin

StoreToRunSection(htLocalMachine, stRun, ‘Имя программы’,

application.exename);

end;

{/codecitation}