Я знаю по крайней мере два способа получения списка дочерних окон фрэйма.
Один из них описан в статье «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