Я знаю по крайней мере два способа получения списка дочерних окон фрэйма.
Один из них описан в статье «8 с половиной долларов» и заключается в обработке события WM_PARENTNOTIFY, которое поступает в окно MDI Client-а. Окно MDI Client это клиентская область окна фрэйма. Это окно можно найти путем перечисления дочерних окон фрэйма: необходимо найти окно с классом MDICLIENT. Либо просто получить его хэндл по AppWindow{Prop:ClientHandle}, где AppWindow – метка окна фрэйма.
Здесь я расскажу о втором способе. Буду краток и покажу только общий смысл.
Этот метод я использую для определения списка дочерних окон в меню Windows (Окна) в классе меню в CFC Library. В Clarion обычно вы используете для этого STD:WindowsList и список окон формируется автоматически.
В основе метода использование функции WinAPI EnumChildWindows. Функция принимает параметрами:
- хэндл окна, для которого необходимо перечислить дочерние окна
- callback процедуру, в которой собственно и происходит перечисление окон
- дополнительный параметр, задаваемый пользователем
Подробнее см. на msdn.com
Хэндл окна, передаваемый в EnumChildWindows – это хэндл клиентской области фрэйма, т.е. AppWindow{Prop:ClientHandle}.
Callback-процедура вызывается до тех пор, пока дочерние окна не закончатся, или из нее не будет возвращено FALSE. Процедура имеет два параметра:
- хэндл дочернего окна
- дополнительный параметр, задаваемый пользователем
EnumChildWindows перечисляет все дочерние окна. Т.е. если на дочернем окне расположены контролы (кнопки, энтри-поля и т.п.), то они тоже попадут в callback-процедуру.
Таким образом, для фильтрации ненужных нам элементов, необходимо определить класс окна. Обычное Clarion-окно имеет класс CLAWINxxxxxx, где xxxxx – цифры :). Для определения класса окна используется API GetClassName.
Если существует связка Browse+Form, то в списке окон отображается заголовок окна Form, а заголовка окна Browse нет. Для фильтрации неактивного окна Browse необходимо фильтровать окна со стилем WS_DISABLED. Для определения стиля окна используется API GetWindowLong.
Для того, чтобы определить какое окно на данный момент активно используется API GetWindowTop.
Реальные примеры использования, вы можете найти в CFC Library начиная с версии 2.1. Это метод FillMDIChildWindows и процедура CFC_MenuEnumerateWindows. И также см. пример std_menu_demo.app метод m:WindowMenu.OnInitMenuPopup.
CFCMenuManager.FillMDIChildWindows PROCEDURE(ULONG in_MDIParent_hwnd)
CODE
FREE(SELF.MDIChildQ)
Err# = CFC_EnumChildWindows(in_MDIParent_hwnd,ADDRESS(CFC_MenuEnumerateWindows),ADDRESS(SELF))
CFC_MenuEnumerateWindows PROCEDURE(ULONG hWnd,LONG lParam)
CurrMng &CFCMenuManager
cstrCaption CSTRING(256)
cstrClassName CSTRING(80)
CODE
IF CFC_GetClassName(hWnd,ADDRESS(cstrClassName),SIZE(cstrClassName))
IF SUB(UPPER(CLIP(cstrClassName)),1,6) = 'CLAWIN'
CurrMng &= (lParam)
IF NOT CurrMng &= NULL
wnd_style# = CFC_GetWindowLong(hWnd,-16)
IF NOT BAND(wnd_style#,CFC_WS_DISABLED) = CFC_WS_DISABLED ! if window is not disabled
IF CFC_GetWindowText(hWnd,ADDRESS(cstrCaption),256)
CLEAR(CurrMng.MDIChildQ)
CurrMng.MDIChildQ.Caption = cstrCaption
CurrMng.MDIChildQ.hwnd = hWnd
ADD(CurrMng.MDIChildQ)
END
END
END
END
END
RETURN TRUE
