Evil_Smile |
Отправлено: 21.01.2007, 12:16 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 57
|
Доброго Времени Суток!
Господа помогите в решении.
Необходимо чтобы после перевода формы из wsMaximized в wsNormal для окна присваивались старые значения. У формы из тех которые мне нужны есть только OnResize но он не подходит у TApplicationEvents только OnMinimize да и те не подходят
Архиватор 7-zip
Help Please!!!
|
|
AVC |
Отправлено: 22.01.2007, 10:14 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
QUOTE (Evil_Smile @ 21.01.2007, 11:16) | Необходимо чтобы после перевода формы из wsMaximized в wsNormal для окна присваивались старые значения. |
Вообще то это происходит автоматически. Винда делает именно так.
Но если надо что то свое, то можно ловить 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 — но вряд ли он Вам подойдёт, т.к. некоторые свойства и опции для него надо прописывать вручную...
|
|
AVC |
Отправлено: 23.01.2007, 09:11 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
QUOTE (aquanet sk @ 22.01.2007, 21:52) | Уважаемые, как сделать так, чтобы при выходе из приложения запоминалось последнее местоположение формы без написания кода? (пусть она будет одна — главная). |
Это напоминает старый анекдот про мечту официанта что бы посетители обедали дома а чаевые присылали по почте.
Без написания кода не выйдет!
Но скоко там того кода? Запомнить 4 интеджера в ини или реестре и потом прочитать.
Если таки решитесь что то сделать сами то туда полезно включить так же и последние нормальные размеры формы, её состояние и реализовать масштабирование при изменении системного шрифта.
Лично у меня там еще стоит применеие стиля к форме но это уже дело вкуса. |
|
aquanet sk |
Отправлено: 24.01.2007, 01:32 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 87
|
QUOTE (AVC @ 23.01.2007, 09:11) | QUOTE (aquanet sk @ 22.01.2007, 21:52) | Уважаемые, как сделать так, чтобы при выходе из приложения запоминалось последнее местоположение формы без написания кода? (пусть она будет одна — главная). |
Это напоминает старый анекдот про мечту официанта что бы посетители обедали дома а чаевые присылали по почте.
Без написания кода не выйдет!
Но скоко там того кода? Запомнить 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
|
Можно пару замечаний общего характера?
Самонадеяно считаю что ответ — да
- Удобнее все параметры свернуть в одну строку.
- Если форма не в нормальном состоянии то вы запомните чушь.
- При смене экранного разрешения или экспорте ини на другую машину форма может "убежать" за экран
- Приложение может иметь более одной формы — это надо предусмотреть.
- Все это, конечно, нужно оформить в самостоятельные функции и вызывать в при создании и закрытии формы.
Примерно так
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: Когда я делал первые шаги в мир С++ , я думал, что все настройки можно сохранять в самом е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: Когда я делал первые шаги в мир С++ , я думал, что все настройки можно сохранять в самом е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
|
ну примеры один длиннее другого , но продуктивно, думаю самая крутая тема в инете получилась из аналогичных. |
|
Doga |
Отправлено: 25.01.2007, 22:48 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
Если посмотреть более старые темы, то можно и не такое увидеть
Отредактировано 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 — компонент более продвинутый, и его использование только для этого — по моему, всё равно что гвозди микроскопом забивать
P.S. Влюбом случае, в обоих компонентах используются те самые GetWindowPlacement и SetWindowPlacement.
Отредактировано Doga — 27.01.2007, 16:09
|
|
aquanet sk |
Отправлено: 27.01.2007, 21:31 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 87
|
понял, а скачать то как/что и присобачить к С++ Builder как? |
|