Список открытых MDI Child окон

Я знаю по крайней мере два способа получения списка дочерних окон фрэйма.

Один из них описан в статье «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