Как сделать окно модальным winapi

Добавил пользователь Евгений Кузнецов
Обновлено: 17.09.2024

"A good example is a debugger when it hits a breakpoint."

Сначала нужно вызвать

SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);

Зтем можно вызывать SetForegroundWindow.

Но это несовсем корректная техника. Для того и изменили поведение функции SetForegroundWindow, чтобы некоторые не доставали своими выскакивающими табличками.

сначала сворачиваем нашу прогу
Application.Minimize;

если "сворачивали в трей", то
if not IsWindowVisible(Application.Handle) then
ShowWindow(Application.Handle, SW_SHOW);

ну и восстанавливаем.
Application.Restore;
а уже при ресторе окно вылазит вперёд

кстати, если кто-то предложит лучший метод (без Minimize), буду очень благодарен

Что значит что с ним что без него?
Функция SystemParametersInfo вообще отработала корректно или ты не проверял на предмет ошибки?

Так вот если не проверял то проверь. Это делается с помощью GetLastError если функция SystemParametersInfo вернёт тебе ноль.

Если же функция отработала успешно, то вызови её же но с параметром SPI_GETFOREGROUNDLOCKTIMEOUT и убедись что она возвратит ноль.

После корректного вызова этой функции и установки свойства SETFOREGROUNDLOCKTIMEOUT в ноль система будет сразу делать окно активным с помощью SetForegroundWindow. Система не будет вызывать функцию FlashWindowEx.

я не знаю, какие у вас винды, а уменя WinXp.
под Win2000 всё точно так же.

Да, такая ситуация тоже возможна и она является штатной. Если текущий foreground-процесс вызвал функцию LockSetForegroundWindow.

Согласен что нужно. Но это просто один из вариантов как всё-таки сделать своё окно поверх всех, даже тогда когда никто этого нехочет и всеми средствами препятствует этому. Появится активное системное модальное окно, а после его закрытия уже делай основым то из своих окно которое необходимо.

На некорректные параметры такую ошибку система не выдаст. С параметрами у него судя по всему всё в порядке. А вот поотключать все лишние запущенные приложения попробовать стоит. Фалит из-за одного из них.

Диалоговые окна существуют модальные(modal dialog box создаются функцией DialogBox)и немодальные (modeless dialog box создаются функцией CreateDialog). Эти две функции загружают шаблон диалогового окна из исполняемого файла прикладной программы и создают выскакивающее окно, которое соответствует спецификации шаблона. Имеются и другие функции, которые создают диалоговое окно, используя шаблоны в памяти; они передают дополнительную информацию в процедуру диалогового окна, как создается диалоговое окно.

Чтобы создать или модальное, или немодальное диалоговое окно, прикладная программа должна снабдить блок диалога шаблоном, чтобы описать стиль и содержание диалогового окна; приложение должно также снабдить диалоговое окно процедурой, чтобы выполнять задачи. Шаблон диалогового окна (dialog box template) - бинарное описание диалогового окна и органов управления, которое оно содержит. Разработчик может создать этот шаблон как ресурс, который будет загружен из исполняемого файла прикладной программы, или создать в памяти, пока прикладная программа выполняется. Процедура диалогового окна (dialog box procedure) - определяемая программой функция повторного вызова, которую система вызывает, когда операционная система получает ввод данных для диалогового окна или задачу для выполнения в блоке диалога. Хотя процедура диалогового окна подобна оконной процедуре, у нее нет тех же самых обязанностей.

Шаблон диалогового окна - это двоичные данные, который описывают диалоговое окно, определяя его высоту, ширину, стиль и органы управления, который он содержит. Чтобы создать диалоговое окно, система или загружает его шаблон из ресурсов в исполняемом файле приложения, или использует шаблон, переданный приложением для неё в глобальной памяти. В любом случае, приложение при создании диалогового окна должно предоставлять шаблон. Разработчик создает ресурсы шаблона, используя компилятор ресурса или редактор диалогового окна. Компилятор ресурса преобразует описание текста в двоичный ресурс, а редактор диалогового окна сохраняет в интерактивном режиме созданное диалоговое окно как двоичный ресурс.

Органы управления диалогового окна

Шаблон устанавливает позицию, ширину, высоту, стиль, идентификаторы и класс окна для каждого органа управления в диалоговом окне. Система создает каждый орган управления путем передачи их данных в функцию CreateWindowEx. Органы управления создаются по порядку, в котором они определены в шаблоне. Шаблон должен определять соответствующее число, тип и порядок органов управления, чтобы гарантировать, что пользователь сможет сделать ввод необходимых данных, чтобы завершить задачу, связанную с диалоговым окном.

Для каждого органа управления шаблон устанавливает значения стиля, которые определяют внешний вид и работу органа управления. Каждый орган управления - это дочернее окно и, поэтому, должно иметь стиль WS_CHILD. Чтобы гарантировать, что орган управления видимый, когда на экране показывается диалоговое окно, каждый орган управления должен иметь также и стиль WS_VISIBLE. Другие, обычно используемые стили окна - это WS_BORDER для органов управления, которые не обязательно имеют рамки, WS_DISABLED для органов управления, которые должны быть блокированы, когда создается первоначальное диалоговое окно и WS_TABSTOP и WS_GROUP для органов управления, к которым можно обращаться, используя клавиатуру. Стили WS_TABSTOP и WS_GROUP используются совместно с клавиатурным интерфейсом диалога, рассмотренным позже в этой главе.

Система преобразует значения координат позиции, размеры ширины и высоты из базовых единиц измерения диалогового окна в пиксели, перед передачей их в функцию CreateWindowEx. Когда система создает орган управления, она определяет диалоговое окно как родительское окно. Это означает, что система всегда воспринимает координаты позиции органа управления как рабочие координаты, относительно верхнего левого угла рабочей области диалогового окна.

Чтобы разрешить пользователю закрыть диалоговое окно, шаблон должен установить, по крайней мере, одну командную кнопку и присвоить ей идентификатор управления IDCANCEL. Чтобы разрешить пользователю выбирать между завершением и отменой задачи связанной с диалоговым окном, шаблон должен установить две командные кнопки. с надписями ОК и Отменить (Cancel), с управляющими идентификаторами IDOK и IDCANCEL, соответственно.

Шаблон устанавливает также и необязательный текст и данные для создания органа управления. Текст обычно предназначен для обозначения кнопок управления или установки начального содержания текста статического органа управления. Данные для создания - это один или несколько байтов данных, которые система передает оконной процедуре органа управления, когда элемент управления создается. Данные для создания полезны для органов управления, которые требуют дополнительной информации о их начальном содержании или стиле, чем это дается другими данными. Например, прикладная программа может использовать данные для создания, чтобы установить начальные параметры и диапазон управления полосой прокрутки.

Процедуры диалогового окна

Каждая процедура диалогового окна имеет нижеследующую форму:

Параметры процедуры служат одной и той же цели, что и в оконной процедуре, параметр hwndDlg получает дескриптор окна блока диалога.

Модальные диалоговые окна блокируют работу всех остальных окон до тех пока они не будут закрыты. При создании модального диалогового окна, система делает его активным окном. Диалоговое окно остается активным до тех пор, пока процедура диалогового окна не вызовет функцию EndDialog, или система не активизирует окно в другом приложении. Ни пользователь, ни приложение не могут сделать окно владельца активным, пока модальное диалоговое окно не разрушится.

Пример WinAPI приложения. Нет главного окна. Все приложение построено на диалоговых окнах.

← →
capkoh © ( 2007-02-06 19:49 ) [0]

Возможно ли простыми методами создать модальное окно на WinAPI? Оно должно быть дополнительным к основному окну. Имею в виду установку стилей и пр. Или это только привилегия MessageBox"ов?

← →
Leonid Troyanovsky © ( 2007-02-06 21:11 ) [1]


> capkoh © (06.02.07 19:49)

> Имею в виду установку стилей и пр. Или это только привилегия
> MessageBox"ов?

See also: DialogBox*

--
Regards, LVT.

← →
capkoh © ( 2007-02-07 18:34 ) [2]

The function displays the dialog box (. ), disables the owner window, and starts its own message loop to retrieve and dispatch messages for the dialog box.

Т.е. даже тут это делается вручную? Кроме того, Dialog Box не полностью блокирует доступ к приложению, а только к окну указанному hWndParent и его чилдам.

Выходит, по-простому никак?

When the owner window is not already disabled, the system automatically disables the window and any child windows belonging to it when it creates the modal dialog box. The owner window remains disabled until the dialog box is destroyed.

Вы должны использовать ключевое слово new при инициализации анимированных значений. Также ключевое слово const используется, когда назначенные значения никогда не меняются в течение его жизненного цикла. Пожалуйста, используйте переменную состояния для хранения анимируемых значений.

Давайте смотреть на Ваш подход № 3, который является очень близко к тому, что Вы хотите. Я подозреваю, что проблема состоит в том, что, когда вторичное приложение закрывается, Windows решает, что это не хочет восстанавливать фокус к отключенному окну. Вы могли попытаться повторно включить свое окно, прежде чем это произойдет, но это, вероятно, будет хитро (и не стоить усилия).

У Вас есть две вещи моделировать: владение и модальность.

Моделировать владение: необходимо установить владельца нового окна дочернего процесса к окну. Это должно облегчить любой z заказывающие проблемы. Хотя я не знаю, работает ли это от другого процесса. Если не затем Вам, возможно, придется присоединить Ваши входные очереди потока и затем назвать его. Или используйте некоторый другой метод инжекции кода.

Для моделирования модальности я думаю, что Вы на правильном пути с EnableWindow и WaitForSingleObjectEx.

Просто логическое предложение,
Возможно, можно создать невидимую модальную форму, и от него используют метод № 1.

Короткий ответ - то, что нет никакого способа беспрепятственно сделать окно в потоке B модальным для окна в потоке A, даже если потоки находятся в том же процессе. При владении кодом для обоих окон Вы можете приближаться, но в этом случае Вы достигнете намного лучших результатов для усилия путем помещения всего UI в одном потоке.

При попытке намекнуть пользователю, что окно B потока модально для потока A, существует большой тонкий Z-порядок и поведения активации, в которых необходимо разобраться (как Вы заметили), чтобы Вы не переносите своего рода эффекта странной долины, где пользователю ясно, что окно B потока пытается быть чем-то, что это не и поэтому кажется поврежденным.

Чтобы избежать, чтобы, я проявил бы этот подход:

Таким образом, если все продолжается обычно и быстро, взаимодействие, может быть бесшовным, но если что-то пойдет не так, как надо с дочерним процессом, или Z-порядок изменяется, то и т.д. будет ясно, почему родительский процесс ожидает и что пользователь должен сделать, чтобы или отменить или продолжать задачу, которую он запустил.

Читайте также: