Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.12.2015, 13:04   #1
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию Запоминание/восстановление размеров и статуса окна при запуске/закрытии программы

Здравствуйте, уважаемые.
Не сложно найти в интернете как при закрытии сохранить в ini, а при открытии восстановить размеры окна. Не сложно предположить, что так же можно запомнить и статус окна, записав в ini переменную, отвечающую за WindowState.
И то ли никто в результате не пользуется в полном объёме этим, то ли ещё что, но нигде я не нашёл как бороться с одним косяком.
Если при работе с программой форму развернуть, а потом свернуть - она примет предыдущие размеры и положение. Однако если при развёрнутом виде форму закрыть с записью размеров и положения - запишутся значения, соответствующие максимальному размеру окна и верхней левой его позиции. Соответственно, если после запуска окно свернуть - оно не примет те размеры и положение, которые были перед разворачиванием, а останется в углу и максимальным.
Может, кто-нибудь знает как с этим бороться?
Пробовал запоминать размеры через CanResize и Resize. Казалось бы логичным: перед изменением размера сохранил предыдущие, и если после изменения изменился статус на Maximized, то записываем предыдущие. Но не тут то было. Для проверки работы этой связки повесил ShowMessage в оба события, который показывал при каком событии вывелось сообщение, ширина и статус окна.
В результате получилось, чот при максимизации из нормального состояния происходит ШЕСТЬ событий!! Вот что выводил ShowMessage при каждом появлении:
Событие (CR - CanResize; R - Resize)/Размер окна (N - нормальный; M - максимальный)/WindowState (N - wsNormal; M - wsMaximized)

1. CR/N/N
2. CR/M/N
3. R/M/N
4. CR/M/M
5. R/M/M
6. CR/M/M

Т.е. программа сначала изменяет размер, создавая и финальное onResize, и только потом уже с этими размерами меняет статус окна. Получается, логично приходящий в голову способ нежизнеспособен. Зачем под конец она снова создаёт CR - вообще для меня загадка.

Единственный вариант, который позволяет более-менее нормально восстанавливать/разворачивать и после закрытия, у меня получился вот такой:

Код:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
  IniF: TIniFile;
begin
  IniF:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'Настройки.ini');
  if Form1.WindowState=wsMinimized then IniF.WriteInteger('Форма','State',2);
  if Form1.WindowState=wsMaximized then IniF.WriteInteger('Форма','State',1);
  if Form1.WindowState=wsNormal then IniF.WriteInteger('Форма','State',0);
  Form1.WindowState:=wsNormal;
  IniF.WriteInteger('Форма','Width',form1.width);
  IniF.WriteInteger('Форма','Height',form1.height);
  IniF.WriteInteger('Форма','X',form1.left);
  IniF.WriteInteger('Форма','Y',form1.top);
  IniF.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  IniF: TIniFile;
  FStt:Integer;
begin
  IniF:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'Настройки.ini');
  Form1.Width:=IniF.ReadInteger('Форма','Width',877);
  Form1.Height:=IniF.ReadInteger('Форма','Height',591);
  Form1.Left:=IniF.ReadInteger('Форма','X',350);
  Form1.Top:=IniF.ReadInteger('Форма','Y',231);
  FStt:=IniF.ReadInteger('Форма','State',0);
  IniF.Free;
  Case FStt of
    0:Form1.WindowState:=wsNormal;
    1:Form1.WindowState:=wsMaximized;
    2:Form1.WindowState:=wsMinimized;
  end;
end;
Может, кто подскажет или придумает как сделать это более нормальным способом?

Встречающийся в просторах интернета вариант "повесить" запоминание размеров на Destroy не подходит, т.к. при этом не срабатывает строка, в которой окно возвращается в нормальное состояние.
Косяк этого варианта: перед закрытием видно, как форма нормализуется. И ещё она не воспринимает запоминание состояния если её закрыть в минимизированном виде.
Ship_1 вне форума Ответить с цитированием
Старый 17.12.2015, 13:27   #2
Filka
Форумчанин
 
Регистрация: 29.10.2015
Сообщений: 273
По умолчанию

http://stackoverflow.com/questions/1...a-delphi-tform
Filka вне форума Ответить с цитированием
Старый 17.12.2015, 14:20   #3
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 15,551
По умолчанию

У меня такое вроде работает:

Код:
type
  TForm1 = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure FormCanResize(Sender: TObject; var NewWidth,
      NewHeight: Integer; var Resize: Boolean);
  private
    winLeft, winTop, winWidth, winHeight: Integer;
  public
    { Public declarations }
  end;
Код:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
  Ini: TIniFile;
begin
  Ini := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'config.ini');
  try
    Ini.WriteInteger('WINDOW', 'Left', winLeft);
    Ini.WriteInteger('WINDOW', 'Top', winTop);
    Ini.WriteInteger('WINDOW', 'Width', winWidth);
    Ini.WriteInteger('WINDOW', 'Height', winHeight);
    Ini.WriteBool('WINDOW', 'Maximized', WindowState = wsMaximized);
  finally
    Ini.Free;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Ini: TIniFile;
begin
  Ini := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'config.ini');
  try
    Left := Ini.ReadInteger('WINDOW', 'Left', Left);
    Top := Ini.ReadInteger('WINDOW', 'Top', Top);
    Width := Ini.ReadInteger('WINDOW', 'Width', Width);
    Height := Ini.ReadInteger('WINDOW', 'Height', Height);
    winLeft := Left;
    winTop := Top;
    winWidth := Width;
    winHeight := Height;
    if Ini.ReadBool('WINDOW', 'Maximized', False) then
      WindowState := wsMaximized
  finally
    Ini.Free;
  end;
end;

procedure TForm1.FormCanResize(Sender: TObject; var NewWidth,
  NewHeight: Integer; var Resize: Boolean);
begin
  if (Left > 0) or (Top > 0) then begin
    winLeft := Left;
    winTop := Top;
    winWidth := Width;
    winHeight := Height;
  end;
end;

Последний раз редактировалось Arigato; 17.12.2015 в 14:28.
Arigato вне форума Ответить с цитированием
Старый 17.12.2015, 18:35   #4
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Arigato, хм, у меня, вроде, тоже работает. Разница с тем подходом, который я пытался неудачно осуществить, лишь в
Код:
if (Left > 0) or (Top > 0) then
Возникает вопрос: форма, раскрываясь на полный экран, в любых случаях верхним левым углом в минусы уходит?
Ship_1 вне форума Ответить с цитированием
Старый 17.12.2015, 18:39   #5
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 15,551
По умолчанию

Цитата:
Сообщение от Ship_1 Посмотреть сообщение
форма, раскрываясь на полный экран, в любых случаях верхним левым углом в минусы уходит?
Не уверен, потому и написал, что вроде работает. Но на двух разных компах с двумя разными ОС сработало. Так что думаю проблем не будет.
Arigato вне форума Ответить с цитированием
Старый 17.12.2015, 19:37   #6
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Если форма закрывалась максимизированной можно просто исходные размеры зафиксированные на этапе проектирования юзать. Или кровь из носу те, что юзер в последний раз использовал?
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 18.12.2015, 10:47   #7
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
Если форма закрывалась максимизированной можно просто исходные размеры зафиксированные на этапе проектирования юзать. Или кровь из носу те, что юзер в последний раз использовал?
Ну размеры этапа проектирования у меня и так почти всегда по умолчанию (за исключением случаев окна по центру). В этот раз нужны именно последние пользовательские. Если нет менее навороченного, чем у Filka и менее условного, чем у Arigato, то вариант Arigato вполне нормален, вроде. Если ещё добавить в FormClose условие "если форма раскрыта и её верхний левый угол меньше нулей, то свернись", то, наверное, это обезопасит и от тех случаев, когда форма, разворачиваясь, всё-таки не заходит за края. Теоретически...
Ship_1 вне форума Ответить с цитированием
Старый 18.12.2015, 15:45   #8
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,774
По умолчанию

Есть системная функция GetWindowPlacement или как-то так. Нужно сохранять то, что она возвращает. Для восстановления SetWindowPlacement.
Vapaamies вне форума Ответить с цитированием
Старый 18.12.2015, 16:01   #9
Filka
Форумчанин
 
Регистрация: 29.10.2015
Сообщений: 273
По умолчанию

http://torry.net/pages.php?id=96
Filka вне форума Ответить с цитированием
Старый 18.12.2015, 16:27   #10
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Filka )) разбираться в чужих компонентах не проще, чем в функции GetWindowPlacement и её параметрах.
Vapaamies, Filka как раз на этот способ и кинул ссылку во втором посте.
Ship_1 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Открытие инфо-окна при запуске программы (Delphi) signalrunners Помощь студентам 5 16.12.2012 16:57
Моментальное закрытие окна при запуске программы tangopanka Общие вопросы C/C++ 2 10.10.2011 09:32
Выполнить код при закрытии окна просмотра segail Microsoft Office Excel 7 08.02.2010 11:22
Confirm при закрытии активного окна Jensi JavaScript, Ajax 4 17.08.2009 19:06
Текст при изменении размеров окна Dj_smart HTML и CSS 2 25.11.2008 23:23