Всем привет! Что-то я не совсем понимаю, как с помощью WinAPI создать своё окно, которое висело бы над другим окном как диалоговое. То есть, не давало сделать какие-либо действия с блокированным окном, пока само не закроется, и не уходило бы на второй план. А то у меня получается. что окошко About может уползти куда-то под основное окно приложения.
Самое примитивное - EnableWindow(,False) на основное окно при показе дочернего и обратно при его скрывании.
Там смысл в том, что главный цикл приложения while GetMessage / DispatchMessage в сущности своей одинаково относится ко всем окнам просто передавая в их обработчики сообщений соответствующие сообщения. При этом создаётся иллюзия их параллельной работы (хотя всё может крутится в одном потоке) если сообщения обрабатываются быстро и визуально не блокируют друг друга (не впадают в слишком долгую работу в потоке). Так вот когда мы делаем код который имитирует блокирующую работу с диалогом (DialogBox), т.е. код застывает в точке вызова DialogBox как будто бы это какой нибудь ReadLine из однопоточного приложения в DOS, то на самом деле в функции DialogBox просто начинает крутится абсолютно такой же цикл while GetMessage / DispatchMessage просто он не выходит оттуда пока диалог не закроется. При этом в цикле вызывается IsDialogMessage которая фильтрует сообщения для модального диалогового окна. Хотя ряд сообщений всё-таки доставляется остальным окнам (типа перерисовки) даже после этой фильтрации, но уже не переключения и тому подобное - фокус в приложении таким образом оказывается захвачен диалоговым окном. В WinAPI очень важно понимать такие нюансы и писать обработку сообщений таким образом чтобы она оставалась совместимой с такими штуками - т.е. если рассчитывать, что message loop устроен всегда по одному шаблону, то диалоговые окна будут работать и в, допустим, оконном OpenGL-приложении. Если же "поломать" основной message loop в таком приложении ориентируясь на интуитивные представления об OpenGL-приложении, то диалоговые окна начнут вызывать заморозку или порчу картинки и т.п.
У меня основная проблема в том, что Event Loop не моего приложения. Т.е. я встраиваю плагин в другое приложение. Когда другое приложение показывает окно моего плагина, есть возможность создавать дочерние диалоговые окна, например About: Так вот этот About имеет свойство уходить под основное окно, если щёлкнуть на заголовок окна, окружающего моё. Соответственно, хочется понять, как удерживать окно поверх своего основного и не давать что-то в нём менять, пока оно не закроется. --- Сообщение объединено, 23 июн 2023 --- Как написал f13nd, EnableWindow может помочь отключить события мыши/клавиатуры на основном окне. Но вопрос удержания другого окна поверх него пока остаётся открытым.
В общем, вроде как помогла комбинация из EnableWindow + обработка вот такого сообщения: Код (Text): case WM_WINDOWPOSCHANGING: { if ((hTransientFor == NULL) || (hTransientFor == HWND_TOP)) break; HWND hPrev = GetTopWindow(GetDesktopWindow()); while (hPrev != NULL) { HWND hCurr = GetWindow(hPrev, GW_HWNDNEXT); // We are already at the top? if (hCurr == hWindow) break; if (hCurr == hTransientFor) { WINDOWPOS *p = reinterpret_cast<WINDOWPOS *>(lParam); p->hwndInsertAfter = hPrev; p->flags &= ~SWP_NOZORDER; break; } // Update pointer hPrev = hCurr; } break; } В этом сообщении мы контролируем, чтобы положение диалогового окна было не ниже окна, над которым мы его показываем (hTransientFor).
Так нужно модальное окно показать? Создаешь нужное окно, родителем которого указываешь disabled окно (EnableWindow (FALSE)).
А они точно диалоговые? Диалог в WinAPI это конкретные обязательства. Как создаются и показываются? По идее вообще без каких либо телодвижений должно было всё работать. Если они действительно диалоговые.
Можно два фактора выделить: а) если не было вызова DialogBox, то нет а) если не было бита в стиле окна Чего-то-там-MODAL, то может и диалог, но не модальный
Так всего-же есть 3 типа диалоговых окон: 1. Немодальное (по умолчанию, не требуется флаг при создании); 2. Модальное внутри своего процесса (флаг DS_MODALFRAME); 3. Системно-модальное. Перекрывает все окна на раб.столе, даже если окно неактивно - видимо это и есть ваш вариант. Создаётся просто добавлением флага DS_SYSMODAL.