Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2011.11.20;
Скачать: [xml.tar.bz2];

Вниз

Сохранение положения форм при последующем входе в программу.   Найти похожие ветки 

 
Abcdef123   (2011-07-27 07:31) [0]

Здравствуйте, Мастера!
Некоторые клиенты наших программ стали использовать несколько мониторов на компе, и просят, чтобы мы изменили настройки положения форм на экране, так как не всегда для этих клиентов теперь удобно работать.
До сегодняшнего момента во всех рабочих проектах нашей компании главная форма проекта fsMDIForm и Position poDefault. Остальное большинство форм fsMDIChild и Position poScreenCenter. А вот клиенты хотят, чтоб если они сдвинут форму как им удобно, чтоб при последующих запусках программы положение формы такое же (измененное ими).
Думаю, что понятно объяснила проблему. В интернете я посмотрела, существуют компоненты на такой случай. Но, начальство не хочет использовать дополнительные компоненты (так как нужно будет при каждой инсталляции дельфи дополнительно еще на это время тратить, а также в будущем заботиться о совместимости версий компонента, когда версию Дельфи будем менять). Так что вопрос такой - поскольку "велосипед" уже кем-то изовретен, можно ли скачать исходники такого компонента, или программу-утилиту, которая поможет мне просто подключить это к проекту и не зависеть от сторонних инсталляций компонентов?
Принимаются любые дельные советы и замечания. Возможно я даже не в правильном направлении иду, и возможно надо бы просто использовать уже какой-то готовый компонент (хотя как я сказала, на данный момент у меня не большой выбор - это решение начальства).
Возможно, кто то уже использует что-то для решения данной задачи, какие бы посоветовали компоненты, в случае если прогу не найти? ...Буду признательна любой информации на эту тему.
Заранее благодарна,
Надежда.


 
И. Павел ©   (2011-07-27 08:06) [1]

Сохраняю позицию форм и размеры элементов на ней  с помощью TINIFile (и набора аналогичных функций из библиотеки AlphaControls - если ее использую).
Для быстрой установки новых компонент можно использовать специальные программы, например - DelphiPi (но начальство вам правильно говорит - для мелких вещей лучше не использовать сторонние компоненты, т.к. с ними могут возникнуть проблемы в будущем).


 
Юрий Зотов ©   (2011-07-27 08:11) [2]

> можно ли скачать исходники такого компонента

Можно. Такой компонент есть в RxLib, ее исходники открыты и есть в Сети. Называется он TFormPlacement. Еще обратите внимание на компонент TFormStorage, он тоже может оказаться очень полезным.


 
Омлет ©   (2011-07-27 08:12) [3]

Компоненты, компоненты... Зачем? Чтобы запомнить и восстановить положение формы, надо несколько строк кода.

Читаем:

   IniFile := TIniFile.Create(GetIniFullFileName);
   try
     with IniFile do
     begin
         if not ReadBool(GENERAL_SECTION, MAXIMIZED_KEY, false) then
         begin
           SystemParametersInfo(SPI_GETWORKAREA, 0, @WorkArea, 0);
           with WorkArea do
           begin
             DW := Right - Left;
             DH := Bottom - Top;
           end;
           W := Min(ReadInteger(GENERAL_SECTION, WIDTH_KEY, Width), DW);
           H := Min(ReadInteger(GENERAL_SECTION, HEIGHT_KEY, Height), DH);
           L := Max(ReadInteger(GENERAL_SECTION, LEFT_KEY, Left), 0);
           T := Max(ReadInteger(GENERAL_SECTION, TOP_KEY, Top), 0);

           if (L + W > DW) then
             L := Max(0, DW - W);
           if (T + H > DH) then
             T := Max(0, DH - H);
           SetBounds(L, T, W, H);
         end
         else begin
           WindowState := wsMaximized;
         end;
   finally
     IniFile.Free;
   end;


Сохраняем, соответственно:

         WriteInteger(GENERAL_SECTION, WIDTH_KEY, Width);
         WriteInteger(GENERAL_SECTION, HEIGHT_KEY, Height);
         WriteInteger(GENERAL_SECTION, LEFT_KEY, Left);
         WriteInteger(GENERAL_SECTION, TOP_KEY, Top);
         WriteBool(GENERAL_SECTION, MAXIMIZED_KEY, WindowState = wsMaximized);


Как-то так. Не проверял на двух мониторах.


 
Юрий Зотов ©   (2011-07-27 08:15) [4]

> для мелких вещей лучше не использовать сторонние компоненты, т.к. с
> ними могут возникнуть проблемы в будущем).

Не вижу таких проблем. Особенно при наличии исходников.

Собственно, компоненты для того и пишутся, чтобы прикладники ими пользовались и тем самым сильно упрощали себе жизнь.


 
Юрий Зотов ©   (2011-07-27 08:19) [5]

> Чтобы запомнить и восстановить положение формы,
> надо несколько строк кода.

А чтобы сохранить/восстановить ВСЕ открытые формы? А также состояние всех контролов на них?


 
Омлет ©   (2011-07-27 08:30) [6]

> Юрий Зотов ©   (27.07.11 08:15) [4]
> Собственно, компоненты для того и пишутся, чтобы прикладники ими пользовались и тем самым сильно упрощали себе жизнь.


Цена такого упрощения не всегда оправдана:
1. Чтобы скомпилировать проект новому разработчику или после переустановки дельфи, надо все компоненты установить.
2. При переходе на новую версию дельфи (особенно в свете последних юникод-версий), не все старые компоненты оказываются работоспособны (не развиваются, заброшены и т.п.). Особенно весело, когда они только в dcu есть. Или приходится заново покупать под нужную версию.
3. Часто компоненты идут большими наборами. Используя всего один из набора, можно ощутимо увеличить размер exe, т.к. там тянется много зависимого кода. А это, к тому же, влияет на скорость запуска программы..

Поэтому люди сводят к минимуму использование компонентов.

> Юрий Зотов ©   (27.07.11 08:19) [5]
> А чтобы сохранить/восстановить ВСЕ открытые формы?


Не намного сложнее.

> А также состояние всех контролов на них?

Такой задачи не было. Сохранение предыдущей сессии (как в браузерах) - отдельная задача. И просто каким-то компонентом её не решить, в общем случае.


 
Омлет ©   (2011-07-27 08:33) [7]

А еще установленные компоненты увеличивают время запуска IDE, что не приносит радости.


 
SQLEXPRESS   (2011-07-27 09:55) [8]

for i := 0 to MDIChildCount - 1 do
 begin
   ToXXX(IntToStr(MDIChildren[i].Left));
   ToXXX(IntToStr(MDIChildren[i].Top));
   ToXXX(MDIChildren[i].ClassName);
 end;
имеем:
x
y
TfrmXXX

-----------
Воссоздавать

все дочки придется тупо-жестко перечислить. Не страшно, сколько там классов-окон .. не 150 же :)
 RegisterClass( TfrmMDISubject );
 ...
 RegisterClass( TfrmMDISubject N );

и далее
CL ;= GetClass("TfrmXXX");
Application.CreateForm(TFormClass(CL), OutForm);
OutForm.top := y;
OutForm.left := x;


 
Dennis I. Komarov ©   (2011-07-27 10:40) [9]

Не проще ли сделать один класс от TForm (или какой там у MDI), подправить его маленько и остальные наследовать уже от него?


 
SQLEXPRESS   (2011-07-27 10:59) [10]


> Dennis I. Komarov ©   (27.07.11 10:40) [9]

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

однако, все формы уже от TForm созданы, еще один уровень не спасет от RegisterClass(


 
Dennis I. Komarov ©   (2011-07-27 11:15) [11]


> однако, все формы уже от TForm созданы,

Unit1;
....
AnyForm: TFormX;

у TFormX перекрываем конструктор(деструктор) читаем (сохраняем) позицию формы.


> еще один уровень не спасет от RegisterClass(

Почему?


 
SQLEXPRESS   (2011-07-27 11:25) [12]


> Почему?

а как?

создай форму имея s:string =  "TFormX";


 
Dennis I. Komarov ©   (2011-07-27 11:47) [13]


> создай форму имея s:string =  "TFormX";

Откуда такое условие? У автора нет ничего подобного. И потом, может быть создан не один экземпляр формы от одного класса, поэтому привязывать координаты формы к классу будет не правильно...


 
SQLEXPRESS   (2011-07-27 12:11) [14]

автор может перебрать все формы на момент закрытия и записать их класс и положение(размеры). Что еще? По-моему, ничего.
и будет у него
Класс1, x, y
Класс2, x, y
Класс2, x, y

затем создавать, при запуске
имеем строку с именем класса - создаем. По координатам устанавливаем.


> может быть создан не один экземпляр формы от одного класса,

правильно
имеем строку с именем класса, такую же,  - создаем. По координатам устанавливаем.

Но как можем создать окно, имея строку с именем?
GetClass(имя) не вернет ничего без RegisterClass(имя)

поэтому, делаем RegisterClass всех возможных MDI чайлдов, а потом getclass
ну или if в ини_старта_ встретилась строка "TFORMX", then RegisterClass("TFORMX")


 
SQLEXPRESS   (2011-07-27 12:13) [15]

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


 
Dennis I. Komarov ©   (2011-07-27 12:27) [16]

Я лишь предложил считывание координат в общем конструкторе. Про создание форм из списка и восстановление рабочей области MDI речи не было.

Вот пользователь закрыл некую MDI-форму, потом приложение. Далее, как я понимаю, все что было должно сохраниться куда-то. Теперь открыли - восстановилось что сохранили. Далее жмем некий кнопарь - открыть (создать) ту самую "некую". Вопрос: где она должна быть и откуда мы это узнаем?

З.Ы.
      Если бы я делал подобное:
Загрузка конфигурации (по умолчанию)
Возможность сохранить ее и соответственно загрузить по желанию пользователя.


 
SQLEXPRESS   (2011-07-27 12:38) [17]


> Про создание форм из списка и восстановление рабочей области
> MDI речи не было

а зачем тогда весь сыр-бор? :)


> Вот пользователь закрыл некую MDI-форму, потом приложение.

НЕ!
и все, на момент закрытия приложения формы не было - потому ничего никуда не храним.
На CloseQuery вешаем сохранение открытых форм, а на старте их восстанавливаем - вот, имхо, вполне ожидаемая реакция от приложения.


> Вопрос: где она должна быть и откуда мы это узнаем?

хороший вопрос :)
Загрузка конфигурации тоже можно тогда.
ее можно как ты сказал сделать


 
Dennis I. Komarov ©   (2011-07-27 13:06) [18]


> а зачем тогда весь сыр-бор? :)

У меня нету :) Пускай думает сама далее, где весь этот мусор хранить, как загружать и т.п.

З.Ы. Еще один камень: Сделали все восстанавливается. Пришел Вася. Расставил, настроил, за... хорошо в общем все :) Потом Петя, ему не понравилось, он подвигал все как ему удобно. Потом Таня, у нее вообще три монитора... Возвращается Вася, ПИ-ПИ-ПИ - он доволен. От радости воткнул Пете...

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


 
SQLEXPRESS   (2011-07-27 13:09) [19]


>  Вася.. воткнул Пете.

??!
так ему и надо тогда :)


 
Abcdef123   (2011-07-28 05:51) [20]

Спасибо всем за отклики и активное обсуждение!!! Попробую некоторые прокомменировать, чтоб прояснить затачу более точно. К примеру насчет пользователей в сообщении [18] - у нас хранится информация о пользователе, каждый под своим именем заходит, так что тут думаю, проблем не будет, можно создавать для каждого пользователя его настройки, INI  файл будет храниться в папке с именем пользователя.
По сообщению [17] - мне кажется тут не правильно поняли. Речь идет не об автоматическом открытии всех форм, которые были открыты в предыдущей сессии, этого как раз делать НЕ надо! Речь идет просто о восстановлении координат форм в случае если ее снова открывают. То есть сейчас все формы открываются в центре экрана, и пользователи, кто работает с 2мя мониторами каждую форму каждый раз вручную тянут влево (к примеру). Вот это и напрягает! Надо, чтоб если уж сместили форму куда-то, чтоб она в следующий раз в тех же координатах и открылась. Кстати, свойство формы Position не published, так что получается я не могу в рантайме поменять, а ведь если менять позицию формы я ж должна отменить значение poScreenCenter сначала. Неужели мне придется в дизайне каждую форму вручную менять? Пусть хоть и один раз, но столько форм и столько проектов, ужас. Или все же можно как то обойти это?
To [2]: Я как раз изначально, когда искала информацию в инете, то наткнулась на эту библиотеку компонент  RxLib и по описанию подумала, что TFormPlacement как раз то что мне нужно, но на том сайте я не смогла найти исходники, и вообще показалось, что сайт давно не обновлялся, подумала, что может уже не поддерживается эта библиотека. Если не трудно, дайте пожалуйста линк, где можно взять исходники этой библиотеки!
Насчет остальных сообщений - пока еще осмысливаю, конкретно честно говоря пока не знаю, что могу сделать, так что вопрос остается открытым и жду продолжения обсуждений в связи с моими дополнительными пояснениями и вопросами.


 
SQLEXPRESS   (2011-07-28 08:52) [21]


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

на onClose запоминаем координаты, потом после создания перемещаем по ним


> свойство формы Position не published

и что?

File - new - other - project - MDIapplication
делаем чайлду  Position = poScreenCenter

дописываем
в

TMainForm
 public
   x,y: Integer;

procedure TMainForm.CreateMDIChild(const Name: string);
var
 Child: TMDIChild;
begin
 { create a new MDI child window }
 Child := TMDIChild.Create(Application);
 Child.Caption := Name;
 Child.Left := x;
 Child.Top := y;
 if FileExists(Name) then Child.Memo1.Lines.LoadFromFile(Name);
end;

---------------

procedure TMDIChild.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 MainForm.x := Left;
 MainForm.y := Top;
 Action := caFree;
end;

все, где закрыли, там и открывается


 
Dennis I. Komarov ©   (2011-07-28 09:55) [22]


>  INI  файл будет храниться в папке с именем пользователя.

Не верно. Папка с приложением должна быть с правами только чтение (вернее программа при таких правах обязана работать). Мелкомягкие отвели специальное место для хранения такого рода информации.


 
Плохиш ©   (2011-07-28 10:43) [23]


> Abcdef123   (28.07.11 05:51) [20]
> Спасибо всем за отклики и активное обсуждение!!! Попробую
> некоторые прокомменировать

Так бы сразу и говорила, что вам шашечки нужны. За это время можно было реализовать минимум пять вариантов, а вы только до комментариев дотумкали.
Наймите программиста в конце концов.


 
Loginov Dmitry ©   (2011-07-28 11:33) [24]


> Можно. Такой компонент есть в RxLib, ее исходники открыты
> и есть в Сети. Называется он TFormPlacement. Еще обратите
> внимание на компонент TFormStorage, он тоже может оказаться
> очень полезным.


В последнее время данный компонент (и всю библиотеку RxLib) не очень активно поддерживают. Не удивлюсь, если его версия для D2010 до сих пор не умеет сохранять местоположение формы в реестре в HKCU. Одним словом, есть риск.
Из-за этой проблемы мне пришлось переводить один из проектов на JEDI. Там есть все компоненты из RxLib и за ними кто-то до сих пор следит.


 
Омлет ©   (2011-07-28 11:41) [25]

> Dennis I. Komarov ©   (28.07.11 09:55) [22]
>>  INI  файл будет храниться в папке с именем пользователя.
> Не верно. Папка с приложением должна быть с правами только чтение (вернее программа при таких правах обязана работать). Мелкомягкие отвели специальное место для хранения такого рода информации.


Она же не сказала, что папки пользователей хранятся в папке приложения. Это вы додумали.


 
Dennis I. Komarov ©   (2011-07-28 11:48) [26]


> Она же не сказала, что папки пользователей хранятся в папке
> приложения. Это вы додумали.

Возможно, но вот телепатор мне говорит именно так, ибо

> можно создавать для каждого пользователя его настройки,
> INI  файл будет храниться в папке с именем пользователя.
>

а не в "AppData\bla-bla..."


 
Игорь Шевченко ©   (2011-07-28 12:14) [27]


> А еще установленные компоненты увеличивают время запуска
> IDE, что не приносит радости.


но уменьшают время на решение задач, что приносит радость


 
MonoLife ©   (2011-07-28 12:15) [28]

AppData\bla-bla..\в папке с именем пользователя\
либо в реестре, если не жаль загаживать..


 
Dennis I. Komarov ©   (2011-07-28 12:26) [29]


> AppData\bla-bla..\в папке с именем пользователя\

не верю :) да и не зачем, ибо
> каждый под своим именем заходит



> либо в реестре, если не жаль загаживать..

точно жаль


 
Anatoly Podgoretsky ©   (2011-07-28 20:24) [30]

> Dennis I. Komarov  (28.07.2011 12:26:29)  [29]

Если разумно относиться, то придется лет 100 загаживать.


 
antonn ©   (2011-07-28 21:22) [31]


> на onClose запоминаем координаты, потом после создания перемещаем
> по ним
>

я предпочитаю WM_EXITSIZEMOVE, т.к. onclose может не наступить :)


 
brother ©   (2011-07-29 05:30) [32]

> onclose может не наступить :)

а ondestroy?)


 
SQLEXPRESS   (2011-07-29 09:40) [33]

Удалено модератором


 
antonn ©   (2011-07-29 11:15) [34]


> а ondestroy?)

а если "onreset" системника? =)


 
brother ©   (2011-07-29 11:31) [35]

тогда по таймеру на 25мск)


 
antonn ©   (2011-07-29 12:12) [36]

и после каждой удачной попытки модальное окошко с уведомлением :)


 
Anatoly Podgoretsky ©   (2011-07-29 12:13) [37]

> brother  (29.07.2011 11:31:35)  [35]

мск это по Москве?



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2011.11.20;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.56 MB
Время: 0.003 c
2-1311793235
Drowsy
2011-07-27 23:00
2011.11.20
При уничтожении модуля данных возникает AV.


15-1311763634
KSergey
2011-07-27 14:47
2011.11.20
Про хитро-задачки


2-1310473287
samstroy
2011-07-12 16:21
2011.11.20
QR коды


2-1312179170
CRLF
2011-08-01 10:12
2011.11.20
"Длинный" путь


4-1251885319
LightGreen
2009-09-02 13:55
2011.11.20
WM_CHAR - кодировка символов





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский