Начало » Программирование » Delphi » Помогите сломать VCL-стереотип - создать окно, поверх только родительского (FormStyle := fsStayOnTop - только для родительского окна)
Помогите сломать VCL-стереотип - создать окно, поверх только родительского [сообщение #2925] |
Sun, 06 August 2023 14:32 |
GrigoryFomin
Сообщений: 91 Зарегистрирован: April 2023
|
Member |
|
|
В вэбэ это часто реализуется, имеет хорошее применение. Нужно, чтобы в MDI-приложении у MDIChild окна создать модальное окно, чтоб оно было модальным и перекрывало ТОЛЬКО свое родительское MDIChild окно, переключаясь на другие MDIChild окна, никакого перекрытия модальным окном не было. Типа как у вкладках браузера - если вылезло на одной вкладке диалоговое модальное окно, на других вкладках от него не было даже запаха. Понятно, что это противоречит VCL-однопоточной концепции, но может это как-то эмулировать? уже думал сделать на основе вкладок TPageControl, на одной странице которого делать "MDIChild окно", а на другой странице - типа "модальное окно" и рисовать на нем фон - изображение первой страницы. Но как-то сильно криворуко. Может, есть что-то более апишное и элегантное?
|
|
|
|
|
|
|
|
|
|
|
Re: Помогите сломать VCL-стереотип - создать окно, поверх только родительского [сообщение #2964 является ответом на сообщение #2960] |
Wed, 09 August 2023 18:52 |
GrigoryFomin
Сообщений: 91 Зарегистрирован: April 2023
|
Member |
|
|
SD писал(а) Wed, 09 August 2023 00:37
Если уж тебе так критично чтобы все окна было не вытянуть за пределы одного. Только в чём фенька?..
Мне надо, чтоб модальное окно перекрыло ТОЛЬКО родительское MDICHild окно, остальные окна MDIChild были доступны. Типа как вкладки браузера - чтоб они были независимы, как разные инстансы одной программы. Например, у меня справочник товаров - сетка - это отдельное окно MDIChild. Такого же типа вкладки ОСТАТКИ, ДВИЖЕНИЕ ТОВАРА и тому подобное. Пользователь может открыть сколько угодно этих окон. В рамках одного окна он хочет изменить товар - вылазит мое модальное окно, которое перекрывает свой MDIChild, но к остальным MDIChild должна быть возможность свободного доступа. Манипуляции с парентами и топмост не дали эффекта. Либо блочится ВСЕ приложение, либо формы ведут себя неадекватно. Выбрал решение - на MDIChild - PageControl со спрятанными заголовками, переключение между табами программно. 1-й таб - сетка общая, другой таб - редактор товара. Еще бы сделать плавное переключение вкладок - было бы вообще супер ))) Современно, модно, молодежно
[Обновления: Wed, 09 August 2023 18:55] Известить модератора
|
|
|
Re: Помогите сломать VCL-стереотип - создать окно, поверх только родительского [сообщение #2965 является ответом на сообщение #2925] |
Wed, 09 August 2023 21:49 |
shalamyansky
Сообщений: 150 Зарегистрирован: August 2022
|
Senior Member |
|
|
В Windows все окна делятся на overlapped и не overlapped. Бывают еще и вовсе не окна - т.е. некие визуальные объекты, ведущие себя на экране подобно окнам, однако не имеющие hwnd и управляемые не через winapi. Overlapped - это самостоятельно плавающие по экрану окна, иногда перекрывающие друг друга, отсюда и название. Не оverlapped - это controls. (Шишков, прости, не знаю, как перевести).
Все overlapped окна одного рабочего стола выстроены в т.н. Z-порядок, не поймите меня неправильно. Управлять этим порядком в принципе можно через некоторые функции, но, поверьте, намучаетесь и нужного результата не добьетесь. Там еще и Delphi в это дело активно вмешивается, и лавировать между Delphi и Windows, как между Сциллой и Харибдой, то еще развлечение.
Любимые вами браузеры, как и другие обычно кроссплатформенные приложения, оперируют не окнами Windows, а собственными объектами, которые для вас выглядят как окна, но ими с точки зрения Windows не являются. Для Windows это всего лишь канва некоего единственного окна, на которой рисуется множество разных фигурок, некоторые похожи на окошки. Каждая браузерная вкладка со всем к ней относящимся хозяйством, в том числе и всплывающими модальными окнами - это одно отдельное окно. Более того, для Оперы, например, это и отдельный процесс, наверное, и для других браузеров так же.
Поэтому, чтобы добиться похожего результата, пишите приложение на фреймворке, не использующем winapi, по-крайней мере, его оконную часть. Под Delphi не знаю такого, может быть, и существует. FireMonkey - что-то такое было как альтернатива VCL, жив, нет? Вдруг подойдет. Как там Lazarus создает графическую оболочку? Я не знаю.
И вот оно вам надо?
[Обновления: Wed, 09 August 2023 21:56] Известить модератора
|
|
|
Re: Помогите сломать VCL-стереотип - создать окно, поверх только родительского [сообщение #2966 является ответом на сообщение #2965] |
Wed, 09 August 2023 23:41 |
GrigoryFomin
Сообщений: 91 Зарегистрирован: April 2023
|
Member |
|
|
shalamyansky писал(а) Wed, 09 August 2023 21:49В Windows все окна делятся на overlapped и не overlapped. Бывают еще и вовсе не окна - т.е. некие визуальные
И вот оно вам надо?
Благодарю за столь развернутый ответ. В WinApi не влазил за 30 лет никогда, пользовался тем, что Delphi - это прежде всего RAD.
Я из поколения - "а какой есть для такого дела компонент????" ))) Ну там на Torry.net
Вообщем, вы меня убедили, что проще свои костыли для этого сделать, тем более, что на PageControl это сделать оказалось не сложно.
Меня другое убивает, если верить соплеменникам в этой эхе (пардон, форуме) - винда предоставляет некий магический новый механизм для MDI/TDI приложений, но в дельфи такого не нашел - плохо ищу или оного не подвезли?
|
|
|
|
|
|
|
|
|
|
Re: Помогите сломать VCL-стереотип - создать окно, поверх только родительского [сообщение #4443 является ответом на сообщение #2925] |
Tue, 13 February 2024 14:44 |
Aleksandr_pro
Сообщений: 24 Зарегистрирован: June 2022
|
Junior Member |
|
|
качать ставить, собирать это ты загнул там в архиве готовый exe, тоже есть и вся соль в одном месте расположена
ниже главный кусочек с комментариями
function TForm.MyShowModal(const ModalCaler:TCustomForm=nil):integer;
var
ActiveWindow: HWnd;
p_WINDOW:Forms.TForm;
begin
if Owner=nil then p_WINDOW:=Screen.ActiveForm else p_WINDOW:=Tform(owner); // если родитель не указан блочим активную форму
ActiveWindow := GetActiveWindow; // запоминаем активное окно
if ModalCaler<>nil then modalform:=ModalCaler else modalform:=TForm(p_WINDOW);
EnableWindow(p_WINDOW.Handle,False); // дисаблим активное окно
ModalResult:=0;
RecreateWnd; // честно не помню зачем
Include(FFormState, fsModal); // вновь открытому окну ставим флаг что оно все же модельное как бы
Show; // показываем текущее окно
try
SendMessage(self.Handle, CM_ACTIVATE, 0, 0); // ставим ему флаг что оно активировано
repeat // далее по аналогии с ShowModal крутимся в цикле пока основная форма работает, при этом так же работуют и остальные формы кроме той что под нами.
Application.HandleMessage;
if (Application.Terminated)or(not visible) then ModalResult:=mrCancel else
if ModalResult<>0 then begin CloseModal;Break;end
until ModalResult<>0;
Result:=ModalResult;
SendMessage(Handle, CM_DEACTIVATE, 0, 0);// по выходу из цикла декактивируем текущую форму
modalform:=nil;
finally
Hide; // прячем текущую форму
end;
Exclude(FFormState, fsModal);
EnableWindow(p_WINDOW.Handle,true); // активируем форму что была под нашей
if GetActiveWindow=self.Handle then SetActiveWindow(ActiveWindow);// и активируем ту что под нами, в целом делаем все тоже что делает ShowModal но только с одной формой а не со всеми.
end;
стало быть делаем так банально
f3:=TForm3.Create(self);
f3.MyShowmodal;
f3.free;
[Обновления: Tue, 13 February 2024 14:45] Известить модератора
|
|
|
|
Переход к форуму:
Текущее время: Tue Dec 10 08:04:08 GMT+3 2024
Общее время, затраченное на создание страницы: 0.00978 секунд
|