Итак, инициализация закончена. Теперь мы можем изменять состояния контролов, идентификаторы которых включены в карту UI. Для этого используется ещё один набор функций с префиксом UI. Все они перечислены в таблице 3.
Функция |
Описание |
BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE) |
Изменяет состояние доступности элементов с идентификатором nIDв соответствии со значением bEnable. Флаг принудительного обновления bForceUpdateзадаётся, когда нужно фактически обновить элемент, даже если его текущее состояние соответствует желаемому и менять ничего не надо. Поскольку все функции используют этот флаг одинаково, я больше не буду на нём останавливаться. |
BOOL UISetCheck(int nID, int nCheck, BOOL bForceUpdate = FALSE) |
Изменяет состояние флага "checked" элементов с идентификатором nIDв соответствии со значением nCheck. Из контролов эту функцию имеет смысл применять только к кнопкам, так как другие контролы не имеют такого флага. nCheckможет принимать одно из трёх значений: 0, если кнопка "отжата", 1, если нажата и 2, если она находится в "третьем состоянии" (кнопка активна, но отрисовывается серым цветом). Третье состояние имеется только у конпок со стилями BS_3STATEили BS_AUTO3STATE. |
BOOL UISetRadio(int nID, BOOL bRadio, BOOL bForceUpdate = FALSE) |
Изменяет состояние флага "radio" элементов с идентификатором nIDв соответствии со значением nRadio. Для контролов эта функция работает аналогично предыдущей. |
BOOL UISetText(int nID, LPCTSTR lpstrText, BOOL bForceUpdate = FALSE) |
Изменяет текст элементов с идентификатором nIDна заданный в параметре lpstrText. |
BOOL UISetState(int nID, DWORD dwState) |
Эта функция позволяет изменить сразу несколько флагов, связанных с элементами nID. Эти флаги объединяются операцией "ИЛИ" и передаются в качестве параметра dwState. Можно использовать флаги UPDUI_DISABLED, UPDUI_CHECKED, UPDUI_CHECKED2(этот флаг соответствует "третьему состоянию" кнопки), UPDUI_RADIOи UPDUI_DEFAULT. Замечу, что флаг UPDUI_DEFAULTможно менять, только используя функцию UISetState. Специальной функции для его изменения нет. Этот флаг позволяет сделать элемент используемым по умолчанию. Обратите внимание, что функция UISetStateне использует флаг bForceUpdateи всегда обновляет элемент, вне зависимости от его текущего состояния. |
DWORD UIGetState(int nID) |
Функция, обратная предыдущей. Возвращает набор флагов, характеризующих состояние элемента. |
Функции, которые мы только что рассмотрели, не изменяют фактическое состояние элементов. Они только записывают новые значения во внутренние структуры класса CUpdateUI<>. Чтобы внесённые изменения вступили в силу, нужно вызвать специальную функцию. Для каждого типа контейнеров существует своя функция: UIUpdateMenuBarдля меню, UIUpdateToolBarдля панели инструментов, UIUpdateStatusBarдля строки состояния и UIUpdateChildWindowsдля контейнера дочерних окон. Каждая из этих функций принимает флаг bForceUpdate. Используйте его, чтобы принудительно обновить все элементы, прописанные в карте UI.
Как это всё работает
Посмотрим, как устроен класс CUpdateUI<>. Карта UI, которую вы создаёте, превращается в массив структур _ AtlUpdateUIMap.
struct _AtlUpdateUIMap {
WORD m_nID;
WORD m_wType;
};
Каждая структура содержит в точности те значения, которые вы передаёте макросу UPDATE_ELEMENTв качестве параметров. Массив завершается структурой со значениями {(WORD)-1, 0}. Для обращения к нему используется функция GetUpdateUIMap, внутри которой он описывается как статическая переменная. Этот массив один на все объекты класса, порождённого от CUpdateUI<>. Кроме этого, каждый объект класса наследует от CUpdateUI<>переменные m_UIElements, m_pUIDataи m_wDirtyType.
m_UIElements — это массив контейнеров, для редактирования которого и используется семейство функций UIAddXXX. Кстати, странно, что разработчики WTL не предусмотрели средства для удаления контейнеров из этого массива. Но тут уже ничего не поделаешь.
m_pUIData — массив структур _AtlUpdateData. Количество элементов в этом массиве в точности соответствует количеству записей в карте UI. Каждая структура _AtlUpdateDataсодержит флаги состояния (те самые, которые меняет функция UISetState) и указатель на строку, которые должны быть назначены элементу. Место для строк распределяется динамически. Вот как описана структура _AtlUpdateUIData.
Читать дальше