Russian Qt Forum
Март 29, 2024, 18:48 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Установить QWidget в качестве модального окна нативному окну [РЕШЕНО]  (Прочитано 9878 раз)
Torvald
Самовар
**
Offline Offline

Сообщений: 118


Просмотр профиля
« : Октябрь 05, 2016, 22:41 »

Такая задача:
Есть приложение, написанное на Delphi, которое грузит dll. Оно представляет собой нативное окно с кнопкой по нажатию которой загружается dll и вызывается из нее функция с параметром HWND - дескриптор этого самого окна.
Dll написана на плюсах с использованием Qt, все что нужно ей сделать - это создать виджет (окно) и отобразить его поверх нативного, а точнее сделаться модальным по отношению к нативному окну.

И здесь проблема:
Код
C++ (Qt)
QWidget *w = new QWidget();
w->setAttribute(Qt::WA_NativeWindow, true);
SetParent((HWND)w->winId(), (HWND)parentHandle);
w->show();
SetParent отображает окно внутри нативного виджета, то есть как mdi child.

Пробовал такой костыль:
Код
C++ (Qt)
long style = GetWindowLong((HWND)w->winId(), GWL_EXSTYLE);
style &= ~WS_EX_MDICHILD;
SetWindowLong((HWND)w->winId(), GWL_STYLE, style);
не помогло

Собственно вопрос:
Как сделать так, чтобы окно отображалось нормально, как обычное модальное окошко?
« Последнее редактирование: Октябрь 06, 2016, 22:08 от Torvald » Записан
Bepec
Гость
« Ответ #1 : Октябрь 06, 2016, 00:25 »

Модальность не может быть для окна. Модальность - это запрет работы с другими окнами приложения. Т.е. либо блокировать всё приложение, либо не блокировать.

PS модальность диалогов и виджетов Qt задаётся флагом void setModality(Qt::WindowModality modality)
Записан
Torvald
Самовар
**
Offline Offline

Сообщений: 118


Просмотр профиля
« Ответ #2 : Октябрь 06, 2016, 01:00 »

Хорошо, пусть будет просто модальное окно. Но я думаю вы меня поняли.

Цитировать
void setModality(Qt::WindowModality modality)
может этот метод и сработает в моем случае, только сначало нужно избавиться от проблемы, что я описал. А именно SetParent отображает окно внутри нативного виджета, то есть как mdi child. А нужно, чтоб было отдельным окном
« Последнее редактирование: Октябрь 06, 2016, 02:07 от Torvald » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Октябрь 06, 2016, 07:39 »

Отображает окно внутри нативного виджета, то есть как mdi child.
В конструкторе виджета есть параметр WindowFlags, где должен быть установлен Qt::Window (или др подходяший) если хотите окно. Еще проще унаследоваться от QDialog

Модальность не может быть для окна.
Может-может Улыбающийся Два (или даже три) модальных она - это запросто

Записан
Torvald
Самовар
**
Offline Offline

Сообщений: 118


Просмотр профиля
« Ответ #4 : Октябрь 06, 2016, 12:28 »

Цитировать
В конструкторе виджета есть параметр WindowFlags, где должен быть установлен Qt::Window (или др подходяший) если хотите окно. Еще проще унаследоваться от QDialog
Это не помогает. Чтобы я ни делал, какие бы флаги не устанавливал - окно все равно отображается внутри нативного, как mdi child. (прикрепил скрин)
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Октябрь 06, 2016, 13:38 »

Это не помогает. Чтобы я ни делал, какие бы флаги не устанавливал - окно все равно отображается внутри нативного, как mdi child. (прикрепил скрин)
Ну а зачем Вы сделали его нативным, и зачем вызвали SetParent из WinAPI? Приложение на дельфях все равно не cможет ему посылать события, придется создавать свой QApplication
Записан
Torvald
Самовар
**
Offline Offline

Сообщений: 118


Просмотр профиля
« Ответ #6 : Октябрь 06, 2016, 13:41 »

Так я и создал свой QApplication.
Если я не сделаю его нативным и не вызову SetParent, то как мне сделать окно модальным? Просто Qt-шное setModality и отображение окна не делает его модальным по отношению к нативному окну.
Записан
Bepec
Гость
« Ответ #7 : Октябрь 06, 2016, 14:12 »

Модальным окно может быть по отношению к приложению, а не к отдельному окну. Это Igors, пусть почитает, просветлится. И таки да - это касаемо Windows. (А если он начнет возбухать = посмотрите же на Qt - то там самодельная модальность Улыбающийся )

По теме - Задать setWindowModality(Qt::ApplicationModal). Это должно сработать.
И вам не надо парентов ставить никому. Окно, создаваемое внутри приложения, принадлежит приложению. И модальность на него просто превосходно поставится должна.
Записан
Torvald
Самовар
**
Offline Offline

Сообщений: 118


Просмотр профиля
« Ответ #8 : Октябрь 06, 2016, 14:25 »

setWindowModality(Qt::ApplicationModal)
тоже не работает. Никакого эффекта. Видимо как раз из-за того, что Qt эмулирует всю эту модальность и к нативному приложению это никак не относится
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Октябрь 06, 2016, 14:39 »

Так я и создал свой QApplication.
Если я не сделаю его нативным и не вызову SetParent, то как мне сделать окно модальным? Просто Qt-шное setModality и отображение окна не делает его модальным по отношению к нативному окну.
А ведь верно. Дельфийское окно получает событие, ну оно ничего не знает о запущенном Qt и обрабатывает себе событие как обычно.

Придется что-то городить. Ну все равно SetParent и.т.п. здесь не помогут. Я бы пробежался по всем окнам приложения и поставил бы всем EnableWindow(wnd, false), а перед закрытием Qt окна вернуть взад. Нормальное решение для "неубогой" системы  Улыбающийся

Записан
Torvald
Самовар
**
Offline Offline

Сообщений: 118


Просмотр профиля
« Ответ #10 : Октябрь 06, 2016, 14:47 »

Вооот, я тоже по-нормальному не смог включить модальность. Поэтому я делал так, как вы описали, но у такого подхода есть свои недостатки - окно отображается в панеле задач и в альт+таб, окно можно скрыть за деактивированным (нативным) окном (имею ввиду z-order) и т.д. Все это делать руками - городить еще больше костылей, что не очень хотелось, отсюда и вопрос возник.
но все равно всем спасибо за ответы
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Октябрь 06, 2016, 15:08 »

Вооот, я тоже по-нормальному не смог включить модальность. Поэтому я делал так, как вы описали, но у такого подхода есть свои недостатки - окно отображается в панеле задач и в альт+таб, окно можно скрыть за деактивированным (нативным) окном (имею ввиду z-order) и т.д. Все это делать руками - городить еще больше костылей, что не очень хотелось, отсюда и вопрос возник.
Я думаю так. Когда открылось окно Qt, запущен его обработчик системных событий. Он принимает все события (извлекает из системной очереди), в том числе и события для дельфийских окон. Но он их не блокирует (с какой стати), а просто отдается на "ф-цию окна". Но он должен проверить фильтр нативного события.  Поэтому вешайте installNativeEventFilter - а там посмотрим
Записан
Torvald
Самовар
**
Offline Offline

Сообщений: 118


Просмотр профиля
« Ответ #12 : Октябрь 06, 2016, 22:08 »

Спасибо за подсказку, сделал так:

Код
C++ (Qt)
QWidget *carrier = new QWidget();
Widget *w = new Widget(carrier);
EnableWindow((HWND)parentHandle, false);
w->show();
QEventLoop loop;
w->connect(w, SIGNAL(closed()), &loop, SLOT(quit()));
loop.exec();
delete w;
delete carrier;
EnableWindow((HWND)parentHandle, true);
SetFocus((HWND)parentHandle);
carrier нужен, чтобы скрыть окно из панели задач.
и
Код
C++ (Qt)
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override
{
if(eventType == "windows_generic_MSG")
{
const MSG *msg = reinterpret_cast<MSG *>(message);
if(msg->message == WM_SETFOCUS && w)
w->activateWindow();
}
return false;
}
а это нужно, чтобы окно было поверх заблокированого, если разворачивать его из панели задач. В общем окошко ведет себя вполне модально)
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.128 секунд. Запросов: 22.