C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
WindowState, Загрузка старых параметров
Evil_Smile
Отправлено: 21.01.2007, 12:16


Дежурный стрелочник

Группа: Участник
Сообщений: 57



Доброго Времени Суток!

Господа помогите в решении.
Необходимо чтобы после перевода формы из wsMaximized в wsNormal для окна присваивались старые значения. У формы из тех которые мне нужны есть только OnResize но он не подходит у TApplicationEvents только OnMinimize да и те не подходят

Архиватор 7-zip

Help Please!!!

User Attached Image Скачать файл
WinState.tar


AVC
Отправлено: 22.01.2007, 10:14


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE (Evil_Smile @ 21.01.2007, 11:16)
Необходимо чтобы после перевода формы из wsMaximized в wsNormal для окна присваивались старые значения.

Вообще то это происходит автоматически. smile.gif Винда делает именно так.
Но если надо что то свое, то можно ловить WM_SYSCOMMAND.
Evil_Smile
Отправлено: 22.01.2007, 11:02


Дежурный стрелочник

Группа: Участник
Сообщений: 57



Доброго Времени Суток!

QUOTE

Вообще то это происходит автоматически.


в том то и дело что она присваивает старые значения

и как в таком случае перехватывать WM_SYSCOMMAND
AVC
Отправлено: 22.01.2007, 11:27


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE

в том то и дело что она присваивает старые значения

Мне казалось что именно это и требовалось ибо
вопрос был
>Необходимо чтобы после перевода формы из wsMaximized в wsNormal для окна присваивались старые значения.

Как отловить WM_...
Воспользоваться поиском по форуму — было неоднократно
Мой вариант можно глянуть тут http://borland.xportal.ru/forum/viewtopic.php?t=20620
aquanet sk
  Отправлено: 22.01.2007, 22:52


Станционный диспетчер

Группа: Участник
Сообщений: 87



Уважаемые, как сделать так, чтобы при выходе из приложения запоминалось последнее местоположение формы без написания кода? (пусть она будет одна — главная). Мне казалось , что раньше это легко делалось где-то в свойствах формы, толи в предыдущих версиях Билдера это было, толи 6-ой у мен обрезанный =) Но мне почему кажется. что было какое-то свойство типа WindowLastState true/false
Doga
Отправлено: 23.01.2007, 07:58


Мастер участка

Группа: Участник
Сообщений: 575



В библиотеке RxLib есть компонент TFormPlacement — но вряд ли он Вам подойдёт, т.к. некоторые свойства и опции для него надо прописывать вручную...


biggrin.gif
AVC
Отправлено: 23.01.2007, 09:11


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE (aquanet sk @ 22.01.2007, 21:52)
Уважаемые, как сделать так, чтобы при выходе из приложения запоминалось последнее местоположение формы без написания кода? (пусть она будет одна — главная).

Это напоминает старый анекдот про мечту официанта что бы посетители обедали дома а чаевые присылали по почте. biggrin.gif

Без написания кода не выйдет!
Но скоко там того кода? Запомнить 4 интеджера в ини или реестре и потом прочитать.

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

Лично у меня там еще стоит применеие стиля к форме но это уже дело вкуса.
aquanet sk
Отправлено: 24.01.2007, 01:32


Станционный диспетчер

Группа: Участник
Сообщений: 87



QUOTE (AVC @ 23.01.2007, 09:11)
QUOTE (aquanet sk @ 22.01.2007, 21:52)
Уважаемые, как сделать так, чтобы при выходе из приложения запоминалось последнее местоположение формы без написания кода? (пусть она будет одна — главная).

Это напоминает старый анекдот про мечту официанта что бы посетители обедали дома а чаевые присылали по почте. biggrin.gif

Без написания кода не выйдет!
Но скоко там того кода? Запомнить 4 интеджера в ини или реестре и потом прочитать.

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

Лично у меня там еще стоит применеие стиля к форме но это уже дело вкуса.

=))) Не, ну если какая-либо функция уже заложена в свойствах компонента, зачем повторно писать, увеличивая размер exe-шника и затрачивая лишнее время, это так все можно можно кодом писать и вообще на Visual C++ перейти -) Я в нем посидел, но это для тех, кто свое время посвящает программированию, а для меня С++ — это увлечение, и поэтому Билдер в самый раз, и надо использовать его потенциал.

P.S. нука выкладывайте полезный код =)
Evil_Smile
Отправлено: 24.01.2007, 09:20


Дежурный стрелочник

Группа: Участник
Сообщений: 57



Доброго Времени Суток!

Приблизительно так, записывает положение, размер окна и WindowState

CODE

//---------------------------------------------------------------------------
//сохранение
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TRegistry *reg = new TRegistry();
reg->RootKey = HKEY_LOCAL_MACHINE;
reg->OpenKey("SOFTWARE\\SavePos\\", true);
reg->WriteInteger("WindowState", Form1->WindowState);
reg->WriteInteger("Height", Form1->Height);
reg->WriteInteger("Width",  Form1->Width);
reg->WriteInteger("Left", Form1->Left);
reg->WriteInteger("Top",    Form1->Top);
reg->CloseKey();
delete reg;
}
//---------------------------------------------------------------------------
//загрузка
void __fastcall TForm1::Button2Click(TObject *Sender)
{
TRegistry *reg = new TRegistry();
reg->RootKey = HKEY_LOCAL_MACHINE;
reg->OpenKeyReadOnly("SOFTWARE\\SavePos\\");
if (reg->ReadInteger("WindowState") == 0)
{
Form1->Height  = reg->ReadInteger("Height");
Form1->Width    = reg->ReadInteger("Width");
Form1->Top  = reg->ReadInteger("Top");
Form1->Left  = reg->ReadInteger("Left");
   }
else
{
Form1->WindowState = reg->ReadInteger("WindowState");
   }
reg->CloseKey();
delete reg;
}
//---------------------------------------------------------------------------


P.S.

я тут накарябал программку не могли бы Вы её протестить так сказать (весит <= 1mb)

заранее благодарен

Отредактировано Evil_Smile — 24.01.2007, 17:25
AVC
Отправлено: 24.01.2007, 10:43


Ветеран

Группа: Модератор
Сообщений: 1583



Можно пару замечаний общего характера?
Самонадеяно считаю что ответ — да smile.gif

- Удобнее все параметры свернуть в одну строку.
- Если форма не в нормальном состоянии то вы запомните чушь.
- При смене экранного разрешения или экспорте ини на другую машину форма может "убежать" за экран
- Приложение может иметь более одной формы — это надо предусмотреть.
- Все это, конечно, нужно оформить в самостоятельные функции и вызывать в при создании и закрытии формы.

Примерно так

CODE

//---------------------------------------------------------------------------

// Save Position, Size and State
PACKAGE void __fastcall IniFormSave  (TForm *frm, const AnsiString &postfix)
{
bool  b;
AnsiString sect, tmp;

sect = NativeFormName(frm) + postfix;
b = (frm->WindowState == wsMaximized)? true: false;
if (b) frm->WindowState = wsNormal;

tmp = AnsiString(frm->Top) + "," +
 AnsiString(frm->Left) + "," +
 AnsiString(frm->Height) + "," +
 AnsiString(frm->Width) + "," +
 AnsiString(b? 1: 0);

Windows_XY->WriteString("Forms", sect, tmp);
}

//---------------------------------------------------------------------------
// Load previos Position, Size and State for Form

PACKAGE void __fastcall IniFormRestore (TForm *frm, bool size, bool setstyle, const AnsiString &postfix)
{
int   ed;
bool  b;
AnsiString sect, tmp;

//     Формы разрабатывались на экране с разрешением в 120 dpi
//     Шрифтом MS Sans Serif 8
if (Form_Scale_Enable && frm->Scaled)
{ int i = Font_Form? Font_Form->Size : 8;
if (i <= 0)  i = 8;
// frm->ScaleBy((DESIGN_PixelsPerInch * i), (Screen->PixelsPerInch * 8));
frm->ScaleBy(i, 8);
}

sect = NativeFormName(frm) + postfix;
tmp = Windows_XY->ReadString  ("Forms", sect, "");
if (tmp.IsEmpty()) { IniFormSave (frm);
     tmp = Windows_XY->ReadString  ("Forms", sect, "");
    }

int t = frm->Top, l = frm->Left, h = frm->Height, w = frm->Width, ws = 0;
sscanf(tmp.c_str(),"%d,%d,%d,%d,%d", &t, &l, &h, &w, &ws);
frm->Top = t;
frm->Left = l;
if (size)
{ frm->Height = h;
frm->Width = w;
}
if (ws) frm->WindowState = wsMaximized;

if (frm->Left < -20 || frm->Left > (Screen->Width -20))  frm->Left = 20;
if (frm->Top  < -20 || frm->Top  > (Screen->Height-20))  frm->Top  = 20;

if (setstyle)  SetStyle (frm);
}

//---------------------------------------------------------------------------

// Использование

void __fastcall TForm1::FormCreate(TObject *Sender)
{
IniFormRestore(this);
...
}

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
...
IniFormSave (this);
}


Windows_XY это TIniFile*.
Не люблю связываться с реестром, да и насторйки в ини проще тиражировать
aquanet sk
  Отправлено: 24.01.2007, 13:11


Станционный диспетчер

Группа: Участник
Сообщений: 87



А с реестром у меня вообще сейчас ерунда получилась, после перезагрузки компа, снова форма появляется на месте по-умолчанию, несмотря на то, что все записи в реестре на месте, и ошибок не происходит. Толи прочитать не успевает, толи что, в общем у меня какие-то глюки походу.
Doga
Отправлено: 24.01.2007, 14:35


Мастер участка

Группа: Участник
Сообщений: 575



Не буду говорить о способе хранения настроек, но для чтения и установки размеров окна (в т.ч. и его состояния) использую APIшные функции:

BOOL GetWindowPlacement(HWND hWnd, WINDOWPLACEMENT *lpwndpl);

и

BOOL SetWindowPlacement(HWND hWnd, CONST WINDOWPLACEMENT *lpwndpl);

Положение, размеры и состояние окна всегда сохраняются и восстанавливаются корректно. Даже если сохранение настроек производится для свёрнутого окна. При следующей загрузке окно будет иметь те же размеры и положение, что были на момент сохранения настроек.
Evil_Smile
Отправлено: 24.01.2007, 16:48


Дежурный стрелочник

Группа: Участник
Сообщений: 57



Доброго Времени Суток!

2Doga, а можно для особо "одаренных" пример использования этих функций.
aquanet sk
Отправлено: 24.01.2007, 22:22


Станционный диспетчер

Группа: Участник
Сообщений: 87



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

Off-top: Когда я делал первые шаги в мир С++ biggrin.gif , я думал, что все настройки можно сохранять в самом еxе-шнике, мол в процессе работы программы автоматом создается временный файл, который перезаписывает новые настройки в exe-файл, и потом стирается тем же exe-шником. А пока же всё храню в реестре, благо мои програмки небольшие, настроек немного.

Отредактировано aquanet sk — 24.01.2007, 22:39
AVC
Отправлено: 25.01.2007, 09:48


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE (aquanet sk @ 24.01.2007, 21:22)
Off-top: Когда я делал первые шаги в мир С++ biggrin.gif , я думал, что все настройки можно сохранять в самом еxе-шнике

Вы не так сильно заблуждались. На линейке 9х это было можно. Там исполняемый exe/dll не блокировался системой.
Doga
Отправлено: 25.01.2007, 14:18


Мастер участка

Группа: Участник
Сообщений: 575



Вот собственно пример использования этих функций.
CODE

//---------------------------------------------------------------------------
//В случае неудачи возвращает NULL
TStringList * __fastcall GetFormState(TForm *Form)
{
 TStringList *FormStatesList = NULL;

 if (Form)
 {
   WINDOWPLACEMENT  WindowPlacement;
   WindowPlacement.length = sizeof(WINDOWPLACEMENT);

   if (GetWindowPlacement(Form->Handle, &WindowPlacement))
   {
     FormStatesList = new TStringList();
     FormStatesList->Clear();

     FormStatesList->Append("СОСТОЯНИЕ ОКНА="  + IntToStr((int)WindowPlacement.showCmd));
     FormStatesList->Append("ВЕРХНЯЯ ГРАНИЦА=" + IntToStr((int)WindowPlacement.rcNormalPosition.top));
     FormStatesList->Append("ЛЕВАЯ ГРАНИЦА="   + IntToStr((int)WindowPlacement.rcNormalPosition.left));
     FormStatesList->Append("НИЖНЯЯ ГРАНИЦА="  + IntToStr((int)WindowPlacement.rcNormalPosition.bottom));
     FormStatesList->Append("ПРАВАЯ ГРАНИЦА="  + IntToStr((int)WindowPlacement.rcNormalPosition.right));
   }
 }  
 
 return FormStatesList;
}
//---------------------------------------------------------------------------
bool __fastcall SetFormState(TForm *Form, TStringList *FormStatesList)
{
 bool Result = false;

 if (Form)
 {
   RECT WorkFrame;
   WINDOWPLACEMENT  WindowPlacement;
   WindowPlacement.length = sizeof(WINDOWPLACEMENT);

   //Получаем текущее состояние окна
   if (GetWindowPlacement(Form->Handle, &WindowPlacement))
   {
     //Получаем рабочую область экрана
     if(SystemParametersInfo(SPI_GETWORKAREA, 0, &WorkFrame, 0))
     {
       if (FormStatesList)
       {
         int StatesCount = 0;
       
         for (int i = 0; i < FormStatesList->Count; i++)
         {
           if (FormStatesList->Names[i] == "СОСТОЯНИЕ ОКНА")
           {
             WindowPlacement.showCmd = FormStatesList->Values[FormStatesList->Names[i]].ToIntDef(9); //SW_SHOWNORMAL
             StatesCount++;
           }
           else if (FormStatesList->Names[i] == "ВЕРХНЯЯ ГРАНИЦА")
           {
             WindowPlacement.rcNormalPosition.top = FormStatesList->Values[FormStatesList->Names[i]].ToIntDef(WorkFrame.top + 50);
             StatesCount++;
           }
           else if (FormStatesList->Names[i] == "ЛЕВАЯ ГРАНИЦА")
           {
             WindowPlacement.rcNormalPosition.left = FormStatesList->Values[FormStatesList->Names[i]].ToIntDef(WorkFrame.left + 100);
             StatesCount++;
           }
           else if (FormStatesList->Names[i] == "НИЖНЯЯ ГРАНИЦА")
           {
             WindowPlacement.rcNormalPosition.bottom = FormStatesList->Values[FormStatesList->Names[i]].ToIntDef(WorkFrame.bottom — 50);
             StatesCount++;
           }
           else if (FormStatesList->Names[i] == "ПРАВАЯ ГРАНИЦА")
           {
             WindowPlacement.rcNormalPosition.right = FormStatesList->Values[FormStatesList->Names[i]].ToIntDef(WorkFrame.right — 100);
             StatesCount++;
           }

           //Все параметры прочитаны, выходим из цикла
           if (StatesCount == 5)
           {
             break;
           }
         }
         delete FormStatesList;  //Если FormStatesList после вызова этой функции всё ещё будет нужен, закоментируйте эту строку
       }

       //Если какой-либо параметр не найден, устанавливаем состояние, положение и размеры окна по умолчанию
       if (StatesCount < 5)
       {
         WindowPlacement.showCmd = SW_SHOWNORMAL; //Другие состояния см. MSDN->WINDOWPLACEMENT
         WindowPlacement.rcNormalPosition.top = WorkFrame.top + 50;
         WindowPlacement.rcNormalPosition.left = WorkFrame.left + 100;
         WindowPlacement.rcNormalPosition.bottom = WorkFrame.bottom — 50;
         WindowPlacement.rcNormalPosition.right = WorkFrame.right — 100;
       }

       if (SetWindowPlacement(Form->Handle, &WindowPlacement))
       {
         Result = true;
       }
     }  
   }
 }  

 return Rsult;
}
//------------------------------------------------------------------------


В качестве входного и выходного параметров здесь используется TStringList, имеющий примерно такое содержание:

QUOTE

СОСТОЯНИЕ ОКНА=9
ВЕРХНЯЯ ГРАНИЦА=50
ЛЕВАЯ ГРАНИЦА=50
НИЖНЯЯ ГРАНИЦА=250
ПРАВАЯ ГРАНИЦА=250
aquanet sk
Отправлено: 25.01.2007, 22:34


Станционный диспетчер

Группа: Участник
Сообщений: 87



ну примеры один длиннее другого biggrin.gif , но продуктивно, думаю самая крутая тема в инете получилась из аналогичных.
Doga
Отправлено: 25.01.2007, 22:48


Мастер участка

Группа: Участник
Сообщений: 575



Если посмотреть более старые темы, то можно и не такое увидеть smile.gif

Отредактировано Doga — 25.01.2007, 22:49
nawok78
Отправлено: 26.01.2007, 10:22


Станционный диспетчер

Группа: Участник
Сообщений: 115



Довелось 1 раз использовать TFormStorage
Коду писать не пришлось помоему вобще
поставил ТРУ где-то и в мастере выбрал нужные поля — все чики-пуки

библиотека RxLib
aquanet sk
Отправлено: 27.01.2007, 00:15


Станционный диспетчер

Группа: Участник
Сообщений: 87



nawok78, а можно поподробнее ? я просто пока не пользовался доп. компонентами, хотелось бы узнать, на какой вкладке палитры компонентов его искать, и как добавить к компонетам вообще?


Я так понял, сам RxLib надо брать здесь — http://rxlib.ru/rx/rx_libr.htm, но какой именно архив скачивать?

Отредактировано aquanet sk — 27.01.2007, 00:24
Doga
Отправлено: 27.01.2007, 16:06


Мастер участка

Группа: Участник
Сообщений: 575



2aquanet sk

Если Вам нужно только сохранение положения окна, то лучше всё-таки использовать TFormPlacement из той же библиотеки. TFormStorage — компонент более продвинутый, и его использование только для этого — по моему, всё равно что гвозди микроскопом забивать smile.gif


P.S. Влюбом случае, в обоих компонентах используются те самые GetWindowPlacement и SetWindowPlacement. wink.gif

Отредактировано Doga — 27.01.2007, 16:09
aquanet sk
Отправлено: 27.01.2007, 21:31


Станционный диспетчер

Группа: Участник
Сообщений: 87



понял, а скачать то как/что и присобачить к С++ Builder как?

Вернуться в Вопросы программирования в C++Builder