Здравствуйте! Хочу узнать о том как реализовать работу с настройками программы. Вот как сделано у меня:
настройки хранятся в реестре.
TOptions = class (TObject)
Path: String;
Name: String;
procedure Load; virtual; abstract;
procedure Save; virtual; abstract;
end;
Опции у меня пока только у грида - настройка видимости полей в БД. Гридов несколько, все на нескольких формах. Хотелось бы абстрагироваться от названий форм,гридов и реализовать работу с ними в общем.То есть надо хранить в реестре назв. формы,грида(их может быть несколько) и в хотя бы список колонок с признаками видимости/невидимости(а лучше настраиваемый список свойств, которые могут храниться в реестре). Как примерно это можно сделать и можно ли? И попутно возникает ещё одна проблема, как хранить информацию о компоненте в реестре. Преобразовывать с помощью потоков в строку - слишком много информации, не все же свойства хранить надо
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
10-08-2008 10:45 | Комментарий к предыдущим ответам
>>>В событии OnShow переводим ValueListEditor в режим редактирования
Не понял, как переводим? Тоже SetFocus-ом? Вроде бы всё надо было перенести в OnPaint из OnShow. Или нет?
>>>в событии OnPaint пробегаем SetFocus-ом по всем ValueListEditor
сделал
>>>После этого подгружаем из файла настройки.
и тут, если в "файле настройки" записан и InplaceEditList, выскакивает исключение. Пробовал во всех последовательностях, не получилось.
Бросьте плз кусочек кода как Вы сохраняете/восстанавливаете, может я чё не так делаю.
10-08-2008 05:53 | Комментарий к предыдущим ответам
InplaceEditList - объект который создается при первом редактировании ValueListEditor-а как описано в вопросе »вопрос КС №64375«. Ошибка при загрузке возникает потому что нет этого самого объекта InplaceEditList. В событии OnShow переводим ValueListEditor в режим редактирования (по умолчанию он в этом режиме), в событии OnPaint пробегаем SetFocus-ом по всем ValueListEditor тем самым создав все InplaceEditList-ы (моё упущение что я в предыдущем посте забыл обратить внимание на то что надо пробегать фокусом по всем ValueListEditor). После этого подгружаем из файла настройки.
У меня такая комбинация работает без ошибок.
10-08-2008 04:04 | Комментарий к предыдущим ответам
По смыслу я пытался загружать форму один раз в onCreate, и сохранять в onDestroy, не используя никаких переменных.
>>>помогло следующее шаманство
Не помогает. Попробовал Ваш вариант, хотя не понял в какой момент Вы сохраняете форму в файл. Чтение формы в onPaint выдает какую же ошибку.
Сохраненная после редактирования грида форма читается с ошибкой т.к. содержит "лишний" обьект. Как этому может помочь перенос чтения в onPaint или куда-то ещё, а главное зачем, я не понял. ИМХО прочитать форму надо при создании, зачем её перечитывать при каждом показе?
действительно, проверил, это так.
помогло следующее шаманство:
перенес из обработчика OnShow в обработчик OnPait и завел отдельную переменную о том была ли загрузка или нет. Т.е. чтобы не на каждый OnPaint грузить форму.
09-08-2008 02:31 | Комментарий к предыдущим ответам
2 Shoor
Пример очень интересный, но если на форму кинуть ValueListEditor то работать он не будет. Вернее будет, если значения в гриде не менять, а если поменять - то не сможет правильно прочитать записанное в файл 'options.set'. Подробнее в »вопрос КС №64375«.
Не могли бы Вы подсказать как решить/обойти эту проблему не убирая ValueListEditor с сохраняемой формы.
Я последнее время часто использую один интересный метод. Создаю форму с опциями. Все опции при использовании в программе беруться прямо с этой формы. Настраиваю форму, как она должна быть по умолчанию. Потом в обработчик onShow формы вставляю такой кусок кода:
CONST FN='options.set';
var i:integer;
begin
if FileExists(FN) then
begin
datafile:=TFileStream.Create(dir+'\'+FN,fmOpenReadWrite);
for i:=0 to self.ComponentCount-1 do
begin
datafile.ReadComponent(self.Components[i]);
if datafile.position=datafile.size then exit; //эта строка
//добавлена для того, чтобы если вы что то
//добавили на форму - код не выдал ошибку при
//первой загрузке файла
end;
end
else
datafile:=TFileStream.Create(FN,fmCreate);
end;
здесь datafile как поле формы.
и на закрытие такой кусок кода:
var i:integer;
begin
datafile.Position:=0;
datafile.Size:=0;
for i:=0 to self.ComponentCount-1 do
datafile.WriteComponent(self.Components[i]);
datafile.Free;
end;
вот, очень удобно. Код совсем не громоздкий, не надо дописывать запись каждого добавленого компонента в процессе доработки приложения, единственно конечно, что он не пишет в реестр, а пишет в файл)
При написании программ я разделяю настройки на три группы:
1. Локальные настройки. Например, ширина столбцов грида - так как в первую очередь ширина столбцов зависит от разрешения монитора локального компьютера. Например, параметры коннекта к БД. Все это можно хранить в ini-файле, либо в реестре.
2. Общие настройки. Например, какие-либо глобальные параметры приложения. Можно хранить только в базе данных в отдельной таблице.
3. Личные настройки пользователя. Например, параметры формирования отчетов, параметры сортировки данных и т.п. Их можно хранить в БД в учетных записях пользователей.
Во-первых TOptions должен быть наследником TComponent. Во-вторых см. »вопрос КС №48140«
Т.е. создаете свойство TGridOptions property Grid: TCustomGrid и работаете с ним.
Основная задача — это необходимость при разрушении Grid, обнулять соответствующее свойство.
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.