Отслеживание открытых дочерних диалогов

В программе на C ++ (embarcadero XE2, vcl) я хотел бы отправлять оконные сообщения от родителя всем дочерним окнам.
Для этого я зарегистрировал окно сообщения, отправив сообщение с PostMessage(handle,msg,wparam,lparam) в цикле для всех дескрипторов и получать его в каждом диалоге с WndProc(TMessage& Message),

Моя проблема состоит в том, чтобы следить за ручками открытого окна. Поскольку большинство диалогов открывается через Show()Несколько из них могут работать одновременно.

До сих пор я использовал std::vector<HWND> хранить оконные ручки Тем не менее, это потребовало бы от меня отслеживания, какой дескриптор все еще действителен одновременно.
Я мог бы решить это, добавив onClose Обработчик диалогов и вызов процедуры в главном потоке с дескриптором диалога в качестве параметра, чтобы его можно было удалить из вектора …

Есть ли более приятное решение, например, самообновляющийся список, как в Application.OpenForms (.СЕТЬ)? Или, может быть, лучший способ уведомить дочерний диалог о событии из основного диалога?

4

Решение

Окно уже отслеживает своих детей внутри, так что вам просто нужно подключиться к этому. Если вы хотите отправить сообщение всем дочерним окнам окна, вам просто нужно рекурсивно перебрать все дочерние окна этого окна, отправив сообщение каждому из них.

Отправной точкой является GetTopWindow функция, который возвращает дочернее окно в верхней части Z-порядка. Затем вы перебираете дочерние окна, вызывая GetNextWindow функция.

MFC на самом деле включает в себя метод, который делает это, называется SendMessageToDescendants, Вы можете написать эквивалент самостоятельно и заменить SendMessage с PostMessage, если вы предпочитаете эту семантику.

void PostMessageToDescendants(HWND   hwndParent,
UINT   uMsg,
WPARAM wParam,
LPARAM lParam,
BOOL   bRecursive)
{
// Walk through all child windows of the specified parent.
for (HWND hwndChild = GetTopWindow(hwndParent);
hwndChild     != NULL;
hwndChild      = GetNextWindow(hwndChild, GW_HWNDNEXT))
{
// Post the message to this window.
PostMessage(hwndChild, uMsg, wParam, lParam);

// Then, if necessary, call this function recursively to post the message
// to all levels of descendant windows.
if (bRecursive && (GetTopWindow(hwndChild) != NULL))
{
PostMessageToDescendants(hwndChild, uMsg, wParam, lParam, bRecursive);
}
}
}

Аргументы такие же, как PostMessage функция, кроме последней: bRecursive, Этот параметр означает только то, что предполагает его название. Если TRUEпоиск дочерних окон будет рекурсивный, чтобы сообщение было отправлено всем потомкам родительского окна (его дочерним элементам, дочерним элементам и т. д.). Если FALSEсообщение будет отправлено только его непосредственным детям.

4

Другие решения

Коди Грей дал правильное решение вопроса, который я задал.

Однако, как показано в комментариях, я задал не тот вопрос.

Мои диалоги были vcl TForms которые были открыты Совой TWindow, что означает, что я использую свойство ParentWindow диалоговых окон, чтобы получить модальное появление:

__fastcall TMyDialog::MyDialog(owl::TWindow* Owner) :TForm(HWND(NULL)){
tf = new TForm(Owner->Handle); //TForm*, Mainwindow calls this dialog
tf->ParentWindow = Owner->Handle; // workaround: owl calls vcl
this->PopupParent = tf; // workaround: owl calls vcl
}

Таким образом, результатом, вероятно, является сочетание дочерних и собственных диалогов.

Что помогло мне получить сообщения окна во всех диалоговых окнах, которые были открыты из главного окна, было так:

struct checkMSG{
HWND handle; UINT msg; WPARAM wparam; LPARAM lparam;
};
checkMSG msgCheck;

BOOL CALLBACK enumWindowsProc(__in  HWND hWnd,__in  LPARAM lParam) {
HWND owner= ::GetParent(hWnd);
if(owner==msgCheck.handle)
::PostMessage(hWnd, msgCheck.msg, msgCheck.wparam, msgCheck.lparam);
return TRUE;
}

void SendToAllWindows(HWND handle, UINT msg, WPARAM wparam, LPARAM lparam){
msgCheck.handle=::GetParent(handle);
msgCheck.msg=msg;
msgCheck.wparam= wparam;
msgCheck.lparam= lparam;
BOOL enumeratingWindowsSucceeded = ::EnumWindows( enumWindowsProc, NULL );
}
  • EnumWindows повторяет все окна во всех приложениях.
  • Чтобы получить только дескрипторы окна моего собственного приложения, я использовал переменную msgCheck хранить дескриптор верхнего уровня и сообщение, которое я хочу отправить.
  • Сейчас пользуюсь GetParent который извлекает Владелец или Родитель или возвращает NULL, если ничего не найдено.
  • В функции обратного вызова сохраненный дескриптор верхнего уровня сравнивается с дескриптором верхнего уровня найденного окна, и если они совпадают, сообщение окна отправляется дескриптору найденного окна
0

По вопросам рекламы [email protected]