Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Сохранение настроек в реестр


Автор: Spiker13 5.7.2006, 22:02
Здравствуйте. Программа с настройками, должна их сохранять и загружать, Ini файлом как-то несолидно, а сохранение и загоузка из реестра не могу понять смысл. Пожалуйста розясните, хотя бы примером сохранения и загрузки переменной. Зарание спасибо.  

Автор: ASGDeveloper 5.7.2006, 22:36
Код

uses Registry;

var
Reg: TRegistry;
str: String;

begin
Reg:=TRegistry.Create;
Reg.RootKey:=HKEY_CURRENT_USER;
Reg.OpenKey('Software\YourSoft', true);
Reg.WriteString('MyVariable', 'hello!');
str:=Reg.ReadString('MyVariable');
Reg.CloseKey;
Reg.Free;
end;
  

Автор: Poseidon 7.7.2006, 00:59
Универсальный алгоритм сохранения настроек

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


Код

R := TRegIniFile.Create;
R.RootKey := HKEY_CURRENT_USER;
R.OpenKey('Software\XXX', True);
R.WriteInteger(Section, 'Left', Left);
R.WriteInteger(Section, 'Top', Top);
R.WriteBool(Section, 'StayOnTop', chStay.Checked);
R.WriteInteger(Section, 'Refresh', Track.Position);
R.WriteInteger(Section, 'Alpha', TrackBarAlpha.Position);
R.WriteBool(Section, 'Snap', chScreenSnap.Checked);
R.WriteBool(Section, 'Baloon', chBaloonHint.Checked);
R.WriteBool(Section, 'vis', boolean(tag));
R.WriteString(Section, 'File', FileName.Hint);
R.WriteInteger(Section, 'Old', Old);
R.WriteInteger(Section, 'First', First);
R.CloseKey;
R.Free

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

Procedure TfrmSettings.SaveSettings;
var settings: TMemoryStream;
R: TRegistry;
j: byte;
S: PChar;
b: boolean;
l: word;
begin
settings := TMemoryStream.Create;

for j := 0 to ControlCount - 1 do
if Controls[j] is TCheckBox then begin
b := TCheckBox(Controls[j]).Checked;
settings.WriteBuffer(b, 1);
end else
if Controls[j] is TEdit then begin
S := PChar(TEdit(Controls[j]).Text);
l := length(S);
settings.WriteBuffer(l, 2);
if l > 0 then settings.WriteBuffer(S^, l);
end;

R := TRegistry.Create;
R.RootKey := HKEY_CURRENT_USER;
R.OpenKey(‘Software\XXX’, true);
settings.Seek(0, soFromBeginning);
R.WriteBinaryData(‘settings’, settings.Memory^, settings.Size);
R.Free;

settings.free;
end;

первое, что делает процедура, это создает поток данных в памяти, он как раз и будет тем буфером, в котором и будут храниться все настройки. Далее процедура начинает перебор всех компонентов на форме. Если очередной компонент является TCheckBox или TEdit, то в буфер записываются их основные свойства, т.е. Checked и Text соответственно. Далее мы записываем буфер как двоичные данные в реестр. 
Процедура загрузки будет выглядеть следующим образом: 

Код

procedure TfrmSettings.LoadSettings;
var settings: TMemoryStream;
R: TRegistry;
buf: PChar;
size: integer;
j: byte;
b: boolean;
l: word;
begin
R := TRegistry.Create;
R.RootKey := HKEY_CURRENT_USER;
R.OpenKey(‘Software\XXX’, true);

if R.ValueExists(‘settings’) then begin
size := R.GetDataSize(‘settings’);
buf := GetMemory(size);
R.ReadBinaryData(‘settings’, buf^, size);

settings := TMemoryStream.Create;
settings.Write(buf^, size);
FreeMemory(buf);
settings.Seek(0, soFromBeginning);
for j := 0 to ControlCount - 1 do
if Controls[j] is TCheckBox then begin
settings.ReadBuffer(b, 1);
TCheckBox(Controls[j]).Checked := b
end else
if Controls[j] is TEdit then begin
settings.ReadBuffer(l, 2);
if l > 0 then begin
buf := GetMemory(l);
settings.ReadBuffer(buf^, l);
TEdit(Controls[j]).Text := copy(buf, 1, l);
FreeMemory(buf)
end;
end;

settings.Free;
end;
R.Free;

end;

Т.е. сначала получаем размер записанных настроек, выделяем под них память, считываем, переносим для удобства в TMemoryStream и считываем. Порядок не нарушается, т.к. пробег по контролам всегда идет по строго определенной последовательности указанной TabOrder. Все! Теперь можно добавлять новые настройки, удалять старые и не изменять код. В данном случае код упрошен, необходимо предусмотреть также обход контролов на панелях (TPanel), группах (TGroupBox) и т.п. 


© Украдено
 

Автор: sandycrazy 25.7.2006, 00:15
зачем засерать реестр?! сколько проблем это создает простым пользователям!!! намного проще пользоваться ini и программа сможет работать без установки! 

Poseidon, забыл написать код для удаления этой фигни из реестра при деинсталяции программы)) 

Автор: Alexeis 25.7.2006, 00:37
Цитата(sandycrazy @  25.7.2006,  00:15 Найти цитируемый пост)
 сколько проблем это создает простым пользователям!!! 
 И сколько же smile. Он вроде специально для этого и создавался, вот только умелых чистельщиков до сих по не придумали. А реестр, он ведь как жесткий диск, требует чистки и дефрагментации. Мало, конечно, стандартов - каждый куда хочет туда и пишет. Если бы все было стандарно, то перенос настроек программ, был бы элементарной операцией. В этом случае каждый решает за себя сам. Я стороник отделения операционной системы, от прикладного, да в общем и обслуживающего софта. Эта концепция помогла, мне значительно увеличить скорость работы компьютера. Сейчас запись в реестр похожа, на режим работы памяти в Windows 95. Под Windows 95 я уже работать не согласен! Так что долой реестр, до тех пор пока не появится "защищеный режим" реестра. 

Автор: Palladin 25.7.2006, 01:47
С одной стороны .ini лучше т.к. пользователь в случае чего сможет чтонить исправить, допустим игра Пираты Карибского Моря, в ней настройки сохранялись именно в файл .ini и у меня была проблема, по дефолту разрешение экрана ставилось 800х600 но у меня на машине почемуто игра с таким разрешением не хотела запускатся, тут-то меня и спас .ini я в него влез и изменил параметр с 800x600 на 1024х768 и всё, но у .ini файлов помимо плюсов есть и минусsmile неумелые пользователи часто портят софт именно тем что залазят в .ini файлы и чтонить изменяют внадежде что программе станет лучше работать или ещё чтоsmile

Такчто на мой взгляд лучше реестр!!! но это моё личное дело smile  

Автор: jack128 25.7.2006, 22:52
Цитата(Spiker13 @  5.7.2006,  22:02 Найти цитируемый пост)
Ini файлом как-то несолидно,

lol. Супер довод!

Цитата(alexeis1 @  25.7.2006,  00:37 Найти цитируемый пост)
 Мало, конечно, стандартов - каждый куда хочет туда и пишет.

рекомендация MS - проста как валенок. Настройки приложения хранить в ветках HKLM\Software\<Company Name>\<Product Name> или HKCU\<Company Name>\<Product Name> 
Ну и во многом это помогло простому юзеру?

Цитата(RooR @  25.7.2006,  01:47 Найти цитируемый пост)
неумелые пользователи часто портят софт именно тем что залазят в .ini файлы и чтонить изменяют внадежде что программе станет лучше работать или ещё что

дык нужно писать приложения так, чтобы кривые настройки не могшли его(приложение) повалить smile 

Автор: Snowy 25.7.2006, 23:00
Цитата(jack128 @  25.7.2006,  22:52 Найти цитируемый пост)
рекомендация MS - проста как валенок. Настройки приложения хранить в ветках HKLM\Software\<Company Name>\<Product Name> или HKCU\<Company Name>\<Product Name> 
Это было в стародавние 9x времена.
На сегодняшний день оптимальней считается линуксовый подход.
То есть данные сохраняются в файл в AppData.
Почему так?
А потому что это home каталог и у юзверя всегда есть права на него, в отличие от папки программы.
Реестр был придуман всего лишь для того, чтобы не нагружать FAT.
C появлением NTFS это уже не актуально.
Что касается реестра - поиск по форуму по слову TRegistry 

Автор: jack128 25.7.2006, 23:22
Цитата(Snowy @  25.7.2006,  23:00 Найти цитируемый пост)
То есть данные сохраняются в файл в AppData.

разговор шел именно о реестре, как я понял.

Цитата(Snowy @  25.7.2006,  23:00 Найти цитируемый пост)
Это было в стародавние 9x времена.

если для тебя - это стародавнии времена, то тебе крупно повезло. 

Автор: Snowy 25.7.2006, 23:37
Цитата(jack128 @  25.7.2006,  23:22 Найти цитируемый пост)
разговор шел именно о реестре, как я понял.
TRegistry.
Если нужно на апи, можно и на апи.
Просто TRegistry удобнее.

Цитата(jack128 @  25.7.2006,  23:22 Найти цитируемый пост)
если для тебя - это стародавнии времена, то тебе крупно повезло. 
Ну не такие древние, как кодинг на асме на ЕС1486 на 8086 процессоре, но то же история.
Я к тому, что сейчас сама MS рекомендуют сохранять в AppData, а не в реестр. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)