Страница 1 из 1

Динамически создаваемые окна

Добавлено: Ср янв 30, 2008 8:47 pm
Max Diesel
Как вероятно все успели заметить, в программе есть диалоговые окна, которые всегда находятся поверх тех окон, с которых их вызвали, а также есть окна, которые отделены от главного окна. Например окно прогресса копирования имеет свою кнопку в панели задач и позволяет переключаться между собой и главным окном программы через Alt+TAB, это же относится к окну Universal Viewer и окну отчета о копировании. Для того чтобы такие окна имели отдельную кнопку в панели задач используется вот такой код при создании окна:

Код: Выделить всё

void __fastcall Twindow_name::CreateParams(TCreateParams &Params)
{
TForm::CreateParams(Params);
Params.ExStyle |= WS_EX_APPWINDOW;
Params.WndParent = 0;
}
Для Deplhi это выглядит так:

Код: Выделить всё

procedure Twindow_name.CreateParams(var Params: TCreateParams);
 begin
   inherited CreateParams(Params);
   Params.ExStyle   := Params.ExStyle or WS_EX_APPWINDOW;
   Params.WndParent := 0;
 end;
Проблема состоит в том, что если из такого окна некое новое диалоговое окно вызвано через ShowModal(), то модальное окно убирает вызвавшее его окно за главное окно программы. Это можно увидеть если в окне прогресса копирования нажать отмену, появившееся окно с вопросом о том, что нужно отменить, будет находиться вроде как поверх главного окна программы, а окно прогресса уйдет за главное. При этом через Alt+TAB не удастся переключиться к главному окну.
То есть как должно быть: динамически созданное окно должно иметь кнопку в панели задач и при этом чтобы была возможность переключаться между этим динамически созданным окном и создавшим его окном через Alt+TAB (и соответственно через кнопки в панели задач), причем когда динамическое окно вызывает модальное диалоговое окно чтобы само оно не уходило за главное и при этом можно было бы переключаться между главным окном и связкой динамического с модальным через Alt+TAB.
Если кто знает как это сделать в C++ Builder (или хотя бы в Delphi), то я буду весьма признателен за помощь в этом вопросе (очень желателен пример и его исходный код). [/color]

Re: Динамически создаваемые окна

Добавлено: Пт фев 01, 2008 1:10 pm
maXmo
По-видимому, придётся ручками делать.
http://softwarer.nm.ru/interface.html#Windows
Модальное окно действует так, словно оно является главным и единственным окном приложения.
Варианты.
1. Попробовать запустить окно прогресса в другом потоке.
2. Вместо того, чтобы сделать окно вопроса модальным, можно скрыть окно прогресса, а потом снова показать после закрытия окна вопроса.
3. Написать свою логику работы модальных окон.

up: К пункту 1.
С дополнительным потоком у меня всё получилось как надо. Но я писал на .нете :roll:
Просто в дополнительном потоке вызвал ShowDialog для окна прогресса и всё.
Проблема я так понимаю в том, что модальное окно лочит на себя весь ThreadInput и другим окнам не даёт.

up2: К пункту 3.
ха-ха, жесть. Предпринял следующую хитрость: сделал все окна немодальными, но
1. окно прогресса сделал owner'ом окна вопроса
2. в окне вопроса в OnLoad делаю Owner.Enabled=false; в OnClosed – Owner.Enabled=true;
В результате при попытке переключиться с окна вопроса на окно прогресса окно вопроса почему-то ведёт себя как модальное (мигает заголовок), но на главное окно пускает беспрепятственно.

Добавлено: Пн фев 04, 2008 2:20 am
Max Diesel
Именно такой метод (через параметр Enabled вызывающего окна) в программе и используется. И для немодальных окон действительно проходит нормально, но есть окна, которые не могут быть немодальными или сделать немодальными их излишне проблемно.
Односительно других потоков - надеюсь существует какой-то менее обходной путь (не хотелось бы в чужом коде, например в Universal Viewer, на незнакомом мне языке пытаться полностью изменить принципы).

Re: Динамически создаваемые окна

Добавлено: Пн фев 04, 2008 12:22 pm
vers
В VCL-приложениях (Delphi/C++ Builder), насколько мне известно, привязка: одна основная форма - один поток. Чтобы побороть похожий баг на http://delphimaster.ru мне советовали создавать еще один поток, а из него уже - новую форму. Вроде так, если ничего не напутал (это было четыре года назад). Можно у спецов оттуда спросить, там довольно быстро отвечают.

Re:

Добавлено: Пн фев 04, 2008 3:16 pm
maXmo
Max Diesel писал(а):(не хотелось бы в чужом коде, например в Universal Viewer, на незнакомом мне языке пытаться полностью изменить принципы).
да вроде не надо ничего менять. Просто его самого этого вьюера создавай и вызывай в другом потоке. Если вьюер однопоточный, то подставы он не заметит. Разумеется, общаться с ним надо будет из того же потока, в котором он был порождён (всё общение на протяжении всего времени жизни объекта вьюера). Трудности могут возникнуть с самой дельфой (вьюер на ней написан?), если она внутри себя начнёт пытаться обращаться к каким-нибудь глобальным ресурсам и будет делать это небезопасно. Если же дельфа потокобезопасна, проблем быть не должно и ни в чей код лезть не надо.

Re: Re:

Добавлено: Пн фев 04, 2008 8:22 pm
Alex
maXmo писал(а):Трудности могут возникнуть с самой дельфой (вьюер на ней написан?), если она внутри себя начнёт пытаться обращаться к каким-нибудь глобальным ресурсам
Так говорить некорректно: как вьюер, так и сам UC написан на VCL. Просто остальная часть UC написана на C++. Вьюер компилируется вместе с UC в один exe-файл, так что у него "специфических" проблем нет.