![]() |
|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
||||
|
||||
![]() Есть форма, в которой заполняются настройки программы.
На этой же форме есть выпадающий список, в котором хранятся разные конфигурации этих настроек. Как сохранить несколько конфигураций и загружать их, если пользователь выберет определённые. Я знаю о существовании iniFiles. Использовать несколько штук этих файлов? Может быть какой-то класс нужен? |
#2
|
||||
|
||||
![]() Может заюзать секции в ини-файле под это?
jmp $ ; Happy End! The Cake Is A Lie. |
#3
|
||||
|
||||
![]() Секции, насколько я понял, делят логически настройки внутри одной конфигурации.
Ваше решение нарушает идеологию. Наверное. |
#4
|
||||
|
||||
![]() Цитата:
Цитата:
Добавлено позже Пример с комбобоксом (в нём названия конфигураций) чтение: Код:
procedure TForm1.ComboBox1Change(Sender: TObject); var IniFile:TIniFile; begin IniFile := TIniFile.Create('cnf.ini'); try with IniFile do begin Label1.Caption:= ReadString(ComboBox1.Text, 'Label1', 'lab1'); Label2.Caption:= ReadString(ComboBox1.Text, 'Label2', 'lab2'); Label3.Caption:= ReadString(ComboBox1.Text, 'Label3', 'lab3'); end; finally IniFile.Free; end; end; Код:
procedure TForm1.Button1Click(Sender: TObject); var IniFile:TIniFile; begin IniFile := TIniFile.Create('cnf.ini'); try with IniFile do begin WriteString(ComboBox1.Text, 'Label1', Edit1.Text); WriteString(ComboBox1.Text, 'Label2', Edit2.Text); WriteString(ComboBox1.Text, 'Label3', Edit3.Text); end; finally IniFile.Free; end; end; Я не понял Вашего вопроса, но всё же Вам на него отвечу! Последний раз редактировалось Alegun, 19.10.2013 в 02:43. |
#5
|
|||
|
|||
![]() Цитата:
Ну, тут вы совершенно не правы. Ini-файл уже давно устаревшая технология. Единственное оправдание использованию ini-файла, это когда его действительно надо править "руками". Кстати, даже в этом случае, писать его рядом с программой больше не получится, по крайней мере начиная с Vista и 2003 (ну мы же не хотим всегда запускать программу от имени администратора?). Реестр, в общем, тоже уже устаревающая технология, которая, кроме того, теперь имеет еще и особенности, в связи с появлением x64. Хотя именно она наиболее используемая в данное время. Еще несколько лет назад MS предложила использовать xml (не помню как он там точно должен был называться, Application.configuration.xml что ли). Но проблемы запрета записи в Program Files это не решало. В принципе, не столько важен формат хранения (ini, xml, binary, etc), как то, где хранить настройки и другие рабочие файлы данных программы (не пользователя, хотя в некоторых случаях даже их, если это всегда один файл). Начиная, если не ошибаюсь, с Windows XP, MS рекомендует использовать для этого "папку" Application Data, путь к которой получается с помощью вызова функции SHGetSpecialFolder. Таких папок для юзера 2: одна для конкретного юзера, вторая - для всех юзеров (у них разные CSIDL'ы). Вот пример из моей программы, которая сохраняет данные пользователя в этом месте (пользовательская AppData) (собрано из разных модулей): Код:
const {$EXTERNALSYM CSIDL_COMMON_APPDATA} CSIDL_COMMON_APPDATA = $0023; function GetSpecialFolderPath(CSIDL : Integer) : String; var Path : PChar; begin Result := ''; GetMem(Path,MAX_PATH); Try If Not SHGetSpecialFolderPath(0,Path,CSIDL,False) Then Raise Exception.Create('Shell function SHGetSpecialFolderPath fails.'); Result := Trim(StrPas(Path)); If Result = '' Then Raise Exception.Create('Shell function SHGetSpecialFolderPath return an empty string.'); Result := IncludeTrailingPathDelimiter(Result); Finally FreeMem(Path,MAX_PATH); End; end; function GetUserAppDataFolderPath : String; begin Result := GetSpecialFolderPath(CSIDL_APPDATA); end; function GetUserFileName(AForcePath : Boolean = False) : String; var APath : String; begin Try APath := GetUserAppDataFolderPath; APath := IncludeTrailingPathDelimiter(APath + 'Visual.Reminder'); If Not DirectoryExists(APath) Then If AForcePath Then If Not ForceDirectories(APath) Then Raise Exception.Create('Can''t force user profile path.'); Except APath := ExtractFilePath(Application.ExeName); APath := IncludeTrailingPathDelimiter(APath); End; Result := APath + 'Reminders.vr'; end; procedure TMainForm.SaveModel; var AFileName : String; begin AFileName := GetUserFileName(True); Try FModel.SaveToFile(AFileName); Except // Hide all exceptions End; end; |
#6
|
||||
|
||||
![]() XML или JSON пользуй.
— Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию |
#7
|
||||
|
||||
![]() Цитата:
На самом же деле, если не следовать слепо моде, внезапно выяснится, что формат ini-файлов сам по себе не так уж и плох, если использовать его с соблюдением требований современных версий Windows, расписанных выше. Отделяем мух от котлет, как говорится. Microsoft из года в год грозится запретить ini-файлы окончательно (интересно, как?), но миллионы программистов по всему миру не могут ошибаться. Для гарантии я бы использовал не системный, а самописный разборщик ini-файлов. Вроде TMemIniFile именно его и реализует, так что его должно быть достаточно. При желании, конечно, можно и в реестре хранить, если стоит задача досадить пользователям и техподдержке. XML-формат -- ни нашим, ни вашим: вроде и текстовый, но его и вручную редактировать трудно, и программный доступ не в пример сложнее ini-файлов. JSON попроще, конечно, но плохо воспринимается именно как формат файла, -- переносы строк в нем факультативны. Для хранения списков в ini-файлах обычно применяют два трюка -- раздел с оглавлением и точечные имена. Примеры можно увидеть в dof- и dsk-файлах, генерируемых средой Delphi. Не стоит путать форумы с богадельнями. © Bargest |
#8
|
||||
|
||||
![]() Цитата:
![]() Я не понял Вашего вопроса, но всё же Вам на него отвечу! |
#9
|
||||
|
||||
![]() Цитата:
Раздел с оглавлением я так понимаю должен выглядеть так? Код:
[Contents] SettName1 = "первые настройки" SettName2 = "вторые настройки" [Первые настройки] a = 1 b = true [Вторые настройки] a = 4 b = true Да и ещё: если мне потребуется сохранить пароль, то в каком виде я должен буду его здесь хранить? В этом случае ini-file с его редактированием руками мне играет не на руку. Последний раз редактировалось Uniq!, 19.10.2013 в 22:39. |
#10
|
|||
|
|||
![]() Цитата:
Читать умеем, да? Когда я говорил, что ini-файлы являются устаревшей технологией, то, естественно, имелось в виду именно то, где их сохранять. На это, кстати, в конце моего поста была отсылка. Сам формат является вполне себе современным, точнее принцип хранения информации в виде пар ключ-значение. Например, почитай о такой штуке, как hBase. Хранение пароля, это отдельная тема. Открытый пароль прекрасно виден даже в бинарном файле. В принципе, если вероятность, что ломать серьезно не будут, то достаточно просто зашифровать любым алгоритмом (да хоть XOR'ом) и поверху закрыть Base64 (для хранения в текстовом виде). Конечно, криптостойкость такого решения оставляет желать лучшего, но она, в общем, достаточна, если ключ недоступен. Более надежная защита - это применение ассиметричного шифрования, да еще и с подписью. При этом приватный ключ надо хранить на каком-нить съемном носителе и/или шифровать симметричным алгоритмом с паролем. Т.е. у пользователя спрашиваем пароль, им расшифровываем приватный ключ, далее с помощью приватного ключа расшифровываем информацию. В своей программе, куски которой я приводил выше, настройки (данные пользователя, сами настройки программы храняться в реестре, т.к. особой ценности не представляют) храняться в сжатом виде (встроенный компрессов на zlib в D7). Сам файл бинарный. Но это мое решение для конкретной задачи, для другой задачи, возможно, потребуется другое решение. |
#11
|
||||
|
||||
![]() Цитата:
Код:
[Contents] SettName1 = "настройки.1" SettName2 = "настройки.2" [настройки.1] a = 1 b = true [настройки.2] a = 4 b = true Цитата:
Для отладки можно реализовать фишку с чтением пароля из ini-файла, если он вписан туда вручную. Программно пароль, соответственно, не сохранять, только читать. Не стоит путать форумы с богадельнями. © Bargest |
#12
|
||||
|
||||
![]() Подъём темы.
Собственно в старой версии всё хранится в ini-файле. Пароли каждый раз вводятся в ручную пользователями. Но настройки переносятся, да простит меня Freeman, через визуальные компоненты ![]() Я думаю сделать так, в ОnCreate главной формы, считать настройки в TRecord (класс для настроек уже нарисовал) из файла, который хранится в AppData. А потом через полюбившуюся мне Код:
function Execute(aDataSet: TDataSet; aUserID, aNo: integer) : boolean; Передавать параметры настроек куда угодно. Возник вопрос: в зависимости от активного пользователя настройки могут быть разными. Кому-то есть доступ к одной вкладке программы, кому-то к другой. Каждый раз лезть с Select'ом в базу не хочу, чтоб узнать какой пользователь залогинился. Значит надо создать какой-то токен внутри программы, идентифицирующий пользователя Сейчас это просто aUserID, который получает не "-1" при удачном вводе пароля. Такого подхода достаточно? или нужно читать информацию по поводу настоящих токенов в {} скобочках и кучей символов внутри (SSID что ли...) |