![]() |
|
Модераторы: Poseidon, Snowy, bems, MetalFan |
![]()
|
|
| Чучмек |
|
||||||||||
|
НЭТ БИЛЭТ ![]() ![]() Профиль Группа: Участник Сообщений: 841 Регистрация: 11.5.2008 Где: СССР Репутация: 14 Всего: 41 |
Если требуется создать более одного экземпляра окна - почему бы и нет?
TFormN.Create - и все ок. Но если программа уже готова(почти), и вдруг возникает необходимость в использования более чем одного экземпляра главного окна. Могут возникнуть проблемы. Вот тому пример Часть проблем примитивные и легко решаемые(если представлять что и зачем), а некоторые - требуют отдельного решения. Поэтому пришлось создавать эту длинную и возможно, никому не нужную тему. Пример. Есть почти готовая рисовалка. Главное окно: Unit1.TForm1 (Form1.AutoSize=true) Image1 - поле для рисования (AutoSize=true) MainMenu1 - меню N1 - "Файл" N2 - "Info" - вызов окна с информацией о программе N3 - Выбор цвета "пера" - (открывается отдельное окно) N4 - вызов окна изменения размера N5 - сохранить художество N6 - открывает окно настроек Unit1.pas
Окно выбора цвета Unit2.TForm2 содержит один ColorBox. Вынес в отдельное окно для примера. unit2.pas
Окно изменения размера Unit3.TForm3 Edit1 - ширина Edit2 - высота Button1 - "Ok" unit3.pas
Окно с информацией о программе Unit4.Form4 Содержит одну лейбу с текстом. Окно настроек (Unit5.Form5) - Два чекбокса CheckBox1- изменение размеров рисунка при растягивании окна мышью CheckBox2- жирное перо Unit5.pas
Project1.dpr
... И захотелось нам... Чтобы... Сразу несколько рисовальных окон было. Стерео картинку рисовать будем. Преобразование разобью на несколько этапов. Описание чуть позже. Это сообщение отредактировал(а) Чучмек - 24.10.2012, 02:09 Присоединённый файл ( Кол-во скачиваний: 5 )
primer.7z 173,70 Kb-------------------- умную мысль держи при себе, а дурной - поделись с другими |
||||||||||
|
|||||||||||
| Rennigth |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1708 Регистрация: 21.6.2004 Где: Moscow Репутация: 49 Всего: 76 |
Чучмек, если я правильно понял проблему(т.е. настройки и т.д. должны применяться ко всем экземплярам окна?), то мне кажется и менюшку и все эвенты в динамике присваивать при создании окна. Другого варианта не вижу... Хотя можно использовать что-то глобальное, реестр или файл на жестком.
-------------------- (* Honesta mors turpi vita potior *) |
|||
|
||||
| Чучмек |
|
|||
|
НЭТ БИЛЭТ ![]() ![]() Профиль Группа: Участник Сообщений: 841 Регистрация: 11.5.2008 Где: СССР Репутация: 14 Всего: 41 |
И это тоже, для себя я здесь большой проблемы не вижу. - Загружать настройки при старте программы, сохранять или при изменении или по завершении,хранить список всех открытых экземпляров окна. На этом нужно будет отдельно остановится. Чуть позже. -------------------- умную мысль держи при себе, а дурной - поделись с другими |
|||
|
||||
| Чучмек |
|
||||||||||
|
НЭТ БИЛЭТ ![]() ![]() Профиль Группа: Участник Сообщений: 841 Регистрация: 11.5.2008 Где: СССР Репутация: 14 Всего: 41 |
Нужно еще одно окно - пожалуйста TForm1.Create(Application).Visible:=true;
Почти полноценное окно и рисовать в нем можно, и сохранить нарисованное. Только не совсем то - размеры изменяются только у первого, цвет "пера" - меняется сразу в двух окнах. При закрытии первого окна завершается приложение. Завершение приложения происходит потому что первое окно является Application.MainForm А при закрытии MainForm происходит завершение приложения. Отсюда - нужно либо в OnClose делать проверку if Self = application.MainForm, и скрывать MainForm вместо закрытия. Либо заменить MainForm. Мне подуше второй вариант. File->New->Form; Form.Name=StartForm; Save->StartFormUnit.pas В project.dpr строку Application.CreateForm(TStartForm, StartForm) делаем первой из Application.CreateForm Строку Application.CreateForm(TForm1, Form1) - убираем В StartForm можно показать заставку при запуске приложения. Но нам это не надо. StartForm показывать не будем. в dpr прописываем Application.ShowMainForm:=false; Создавать первый экземпляр TForm1 можно в StartForm.OnCreate При создании окна, возможно, необходимо передать ему начальные параметры. Для этого можно написать отдельную функцию NewForm. А можно переопределить конструктор TForm1
[b]StartFormUnit.pas[b]
В MainMenu1 добавляем пункт N7 - "новое окно"
При закрытии окна TForm1 необходимо делать проверку - если закрывается последнее окно TForm1 - завершить приложение. Можно держать количество открытых TForm1 в отдельной переменной. Можно создать список открытых TForm1. А можно использовать список Application.Components
Одну проблему устранили... Это сообщение отредактировал(а) Чучмек - 25.10.2012, 10:40 -------------------- умную мысль держи при себе, а дурной - поделись с другими |
||||||||||
|
|||||||||||
| Чучмек |
|
||||||
|
НЭТ БИЛЭТ ![]() ![]() Профиль Группа: Участник Сообщений: 841 Регистрация: 11.5.2008 Где: СССР Репутация: 14 Всего: 41 |
Теперь вторая проблема - на все окна TForm1 в панели задач одна кнопка "Project1"
Это происходит потому, что при создании нового окна (используется CreateWindowEx) в параметре hWndParent передается Application.Handle. И все окна приложения являются дочерними окнами Application. (Кто не знал - Application тоже окно, причем главное окно приложения). Дочерние окна своей кнопки в панели задач не имеют, а кнопка "Project1" - кнопка от Application. Отсюда решение - скрыть Application а в качестве hWndParent, при создании окна TForm1, передавать 0 или GetDesktopWindow() Переопределяем CreateParams
И в dpr добавляем строчку ShowWindow(Application.Handle,SW_HIDE)
-------------------- умную мысль держи при себе, а дурной - поделись с другими |
||||||
|
|||||||
| Чучмек |
|
||||||||||||||||||||||||||
|
НЭТ БИЛЭТ ![]() ![]() Профиль Группа: Участник Сообщений: 841 Регистрация: 11.5.2008 Где: СССР Репутация: 14 Всего: 41 |
Идем дальше. "Причесывание" кода. Все глобальные переменные, которые используются для сохранения промежуточных состояний и связи межу методами/событиями TForm1 вносим внутрь класса TForm1. В методах TForm1 везде где встречается Form1 - меняем на self или вообще убираем. Стоку var Form1: TForm1; - удаляем. (Переменную Form1, для удобства, можно перенести внутрь TForm1)
Если Form1 встречается в функциях/процедурах - делаем их либо методами TForm1, либо добавляем в функции дополнительный параметр. Было
стало
или
Определяемся с дополнительными окнами. Какие из дополнительных окон будут существовать в единственном экземпляре,а какие - в нескольких(по одному на каждый экземпляр TForm1) Так в моем примере окно с информацией о программе Form4 и окно настроек Form5 будут в единственном экземпляре. А окно выбора цвета TForm2 и окно изменения размера TForm3 - для каждого экземпляра TForm1. Для "многоэкземплярных" окон(форм) - аналогично "причесываем" код. Из юнита формы удаляем переменную var FormN:TFormN. Из dpr удаляем строку создания формы Application.CreateForm(TFormN, FormN); В TForm1 добавляем переменную на каждую "многоэкземплярную" форму. При создании экземпляра TForm1 создаем и связанные "многоэкземплярные" формы.
Если в методах "многоэкземплярных" форм было обращение к Form1 или к глобальной переменной из Unit1(мы ее уже перенесли в TForm1) то возможны варианты: a) Добавить в TFormN переменную Form1:TForm; инициализировать ее в переопределенном конструкторе, или при создании из TForm1, или при первом вызове ( if not Assigned(form1) then form1:=self.Owner as tform);использовать как (form1 as TForm1). б) сразу использовать (Owner as TForm1) Если из одной вспомогательной "многоэкземплярной" формы было обращение к другой - заменить на обращение через TForm1 - (Owner as TForm1).Form3 Для "одноэкземплярных", если использовалось обращение к TForm1, необходимо разделить обращения на общие(ко всем экземплярам главного/рабочего окна) и частные(к одному). Так в окне настроек было два пункта -"Изменение размера мышью" и "Жирное перо" Пусть "Изменение размера мышью" - настройка для всех окон, а "Жирное перо" - только для окна вызвавшего окно настроек. Было
Стало
Для опции "Жирное перо" Добавим в TForm5 переменную Form1
Вызов окна настроек
При закрытии экземпляра TForm1 открытые связанные "многоэкземплярные" окна закроются сами (передаем Self в TFormN.Create), а вот "одноэкземплярные" остаются открытыми (родитель - Application) . Иногда это не нужно. Если мы, в окне настроек, чекним "Жирное перо", после закрытия окна вызвавшего настройки, - получим "Invalid class typecast". Окно настроек нужно закрыть
Это сообщение отредактировал(а) Чучмек - 26.10.2012, 15:44 -------------------- умную мысль держи при себе, а дурной - поделись с другими |
||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||
| Чучмек |
|
|||
|
НЭТ БИЛЭТ ![]() ![]() Профиль Группа: Участник Сообщений: 841 Регистрация: 11.5.2008 Где: СССР Репутация: 14 Всего: 41 |
Теперь собственно самое интересное.
Потребность в псевдомодальном режиме. Если мы из экземпляра TForm1 вызовем окно в модальном режиме (MessageBox/ShowMessage/TCommonDialog.Execute/FormN.ShowModal мы получим блокировку всех остальных окон до закрытия модального окна. Это не есть гуд. Остальные экземпляры TForm1 и связанные с ними окна должны оставаться свободными. Если бы каждый экземпляр TForm1 имел свой цикл обработки сообщений и свой поток - нет проблем. Однако,в Delphi, по крайней мере в 7-ой, такого нет. -------------------- умную мысль держи при себе, а дурной - поделись с другими |
|||
|
||||
![]()
|
| Правила форума "Delphi: Общие вопросы" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Delphi: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |