- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Программирование на Visual C++. Архив рассылки - Алекс Jenter
Шрифт:
Интервал:
Закладка:
...
END_MSG_MAP()
Во вторых, после того, как ваш дилог создан, необходимо инициализировать внутренние структуры WTL, связанные с масштабированием. Это делается при помощи функции DlgResize_Init. Удобно вызывать её из обработчика сообщения WM_INITDIALOG. Функция DlgResize_Initимеет следующий прототип:
void DlgResize_Init(bool bAddGripper = true, bool bUseMinTrackSize = true,
DWORD dwForceStyle = WS_THICKFRAME | WS_CLIPCHILDREN)
В большинстве случаев на параметры можно не обращать внимание, так как значения по умолчанию вполне удовлетворяют всем нуждам. Параметр bAddGripper указывает, нужно ли добавить к диалогу "гриппер" – маленький уголок, за который можно ухватиться курсором и изменить размеры диалога. Флаг bUseMinTrackSize определяет, нужно ли ограничивать минимальные размеры диалога. В большинстве случаев это хорошая идея, так как сильно уменьшенный дилог всё равно плохо выглядит и не удобен для работы с ним. Минимальный размер диалога хранится в переменной m_ptMinTrackSize, которую ваш класс диалога наследует от класса CDialogResize<>. По умолчанию в неё записывается первоначальный размер диалога (тот, который установлен в момент вызова функции DlgResize_Init). Вы можете записать туда любое другое значение. Что касается параметра dwForceStyle, то это просто стиль, который принудительно назначается диалогу в функции DlgResize_Init.
Ещё одна функция из класса CDialogResize<>, о которой следует упомянуть, – DlgResize_UpdateLayout. Эта функция принудительно пересчитывает координаты всех контролов в зависимости от переданных ей размеров диалога (cx и cy). Именно она вызывается из обработчика сообщения WM_SIZE, но при необходимости вы можете вызывать её в любом другом месте.
Как составлять карту масштабированияНа самом деле, единственная проблема с классом CDialogResize<> состоит в том, чтобы правильно составить карту масштабирования. Для этого нужно чётко понимать, как работают флаги DLSZ_XXX. Эти флаги по-разному действуют на контрол в группе или без неё.
Сначала посмотрим, как флаги DLSZ_XXX действуют на контрол, не включённый в группу. Допустим, размеры диалога изменились на dx и dy соответственно. Тогда:
• DLSZ_SIZE_X: ширина контрола изменяется на dx.
• DLSZ_SIZE_Y: высота контрола изменяется на dy.
• DLSZ_MOVE_X: контрол двигается вдоль оси x на dx . Флаг DLSZ_SIZE_X при этом игнорируется.
• DLSZ_MOVE_Y: контрол двигается вдоль оси y на dy . Флаг DLSZ_SIZE_Y при этом игнорируется.
Как видно из этого описания, задавать одновременно флаги DLSZ_MOVE_X и DLSZ_SIZE_X (а также DLSZ_MOVE_Y и DLSZ_SIZE_Y) бессмысленно, так как в этом случае будут учитываться только флаги DLSZ_MOVE_*.
Описанная схема масштабирования довольно примитивна. Так, очевидно, что к двум расположенным рядом контролам нельзя применять флаг DLSZ_SIZE_*, так как они оба увеличат размер и "заедут" друг на друга. И всё-таки во многих случаях такого механизма оказывается достаточно. Для примера рассмотрим типичный диалог выбора файла (рисунок 2).
Рисунок 2. Схема диалога открытия файла
При масштабировании логично изменять размер контролов диалога следующим образом: растягивать IDC_LEFT_PANE на всю высоту диалога, растягивать IDC_COMBO по горизонтали, отодвигая IDC_TOOLBAR до предела вправо, отодвигать IDC_NAME и IDC_FILTER вниз и растягивать по горизонтали, перемещать кнопки IDOK и IDCANCEL в правый нижний угол и занимать списком файлов IDC_FILE_LIST всё оставшееся место. Чтобы воплотить в жизнь эту схему, следует записать карту масштабирования следующим образом:
BEGIN_DLGRESIZE_MAP(COpenFileDialog)
DLGRESIZE_CONTROL(IDC_LEFT_PANE, DLSZ_SIZE_Y)
DLGRESIZE_CONTROL(IDC_COMBO, DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_TOOLBAR, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_FILE_LIST, DLSZ_SIZE_X | DLSZ_SIZE_Y)
DLGRESIZE_CONTROL(IDC_NAME, DLSZ_MOVE_Y | DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_FILTER, DLSZ_MOVE_Y | DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDOK, DLSZ_MOVE_Y | DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDCANCEL, DLSZ_MOVE_Y | DLSZ_MOVE_X)
END_DLGRESIZE_MAP()
Теперь поговорим о контролах, объединённых в группу.
ПРЕДУПРЕЖДЕНИЕ
Реализация групп в WTL подразумевает, что все контролы в группе должны располагаться рядом друг с другом по горизонтали или по вертикали. Флаги, которые вы задаёте для контролов в группе, должны относиться только к одному направлению (или X, или Y), но не к обоим сразу. Несоблюдение этих условий приведёт к странным эффектам. Кроме того, напомню ещё раз, что группы не могут быть вложенными.
Группы обрабатываются следующим образом. Сначала вычисляются координаты огибающего прямоугольника группы, то есть минимального прямоугольника, содержащего все контролы в ней. Далее размеры этого прямоугольника увеличиваются на dx и dy соответственно (dx и dy имеют то же значение, что и в обсуждении выше). После этого к каждому контролу в группе применяются следующие правила:
• DLSZ_MOVE_X: контрол сдвигается вдоль оси X пропорционально изменению ширины группы (то есть её огибающего прямоугольника).
• DLSZ_MOVE_Y: контрол сдвигается вдоль оси Y пропорционально изменению высоты группы.
• DLSZ_SIZE_X: действует аналогично DLSZ_MOVE_X, но ширина контрола также изменяется пропорционально изменению ширины группы.
• DLSZ_SIZE_Y: действует аналогично DLSZ_MOVE_Y, но высота контрола также изменяется пропорционально изменению высоты группы.
Проиллюстрирую сказанное простым примером. Допустим, у нас есть диалог с тремя расположенными в ряд кнопками. Если написать для него карту масштабирования вида:
BEGIN_DLGRESIZE_MAP(CMyDialog)
BEGIN_DLGRESIZE_GROUP()
DLGRESIZE_CONTROL(IDC_BUTTON1, DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_BUTTON2, DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_BUTTON3, DLSZ_SIZE_X)
END_DLGRESIZE_GROUP()
END_DLGRESIZE_MAP()
то этот диалог будет масштабироваться следующим образом:
Рисунок 3. Масштабирование с использованием групп
Как это всё работаетМы не будем надолго задерживаться на внутренней реализации класса CDialogResize<>, так как там нет почти ничего интересного. Когда вы вызываете функцию DlgResize_Init, начальные положения всех контролов в диалоге запоминаются во внутренних структурах WTL. Функция DlgResize_UpdateLayout использует новые размеры диалога и сохранённые ранее координаты контролов, чтобы назначить им новое положение в соответствии с заданными флагами. Что касается карты масштабирования, она просто превращается в статический массив структур _AtlDlgResizeMap, для доступа к которому используется функция GetDlgResizeMap. Структура _AtlDlgResizeMap хранит заданные вами в карте значения:
struct _AtlDlgResizeMap {
int m_nCtlID;
DWORD m_dwResizeFlags;
};
Хочу отметить несколько особенностей реализации класса CDialogResize<>, которые можно использовать в своих целях.
1. Элемент может встречаться в карте масштабирования более одного раза.
2. Элемент, не включённый в группу, двигается относительно его текущего положения.
3. Элемент, включённый в группу, масштабируется с учётом его начального положения (но без учёта его текущей позиции).
Таким образом мы можем, к примеру, отмасштабировать элемент по горизонтали, включив его в группу, а затем отдельно увеличить его высоту. Пример диалога с тремя кнопками, который мы рассмотрели выше, имел один недостаток: при увеличении высоты диалога кнопки не растягивались по вертикали. Теперь мы знаем, как решить эту проблему:
BEGIN_DLGRESIZE_MAP(CMyDialog)
BEGIN_DLGRESIZE_GROUP()
DLGRESIZE_CONTROL(IDC_BUTTON1, DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_BUTTON2, DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_BUTTON3, DLSZ_SIZE_X)
END_DLGRESIZE_GROUP()
DLGRESIZE_CONTROL(IDC_BUTTON1, DLSZ_SIZE_Y)
DLGRESIZE_CONTROL(IDC_BUTTON2, DLSZ_SIZE_Y)
DLGRESIZE_CONTROL(IDC_BUTTON3, DLSZ_SIZE_Y)
END_DLGRESIZE_MAP()
Кроме этого, можно включить элемент в несколько групп. Хотя на его местоположение повлияет только последняя группа, этот приём позволит сложным образом влиять на другие контролы. Но не стоит забывать о чувстве меры. Такие приёмы делают вашу программу более запутанной и более медлительной. Нетривиальное масштабирование контролов в диалоге лучше реализовать вручную, а не заниматься неочевидными фокусами с CDialogResize<>.
КонтролыКонтролы – ещё один важный элемент операционной системы Windows. Во времена DOS каждому программисту зачастую приходилось изобретать собственный графический интерфейс. Под Windows задача упростилась: хотя сложные нестандартные "фичи" пользовательского интерфейса по-прежнему приходится разрабатывать вручную, в вашем распоряжении всегда есть базовый набор элементов, которые можно использовать для взаимодействия с пользователем или попытаться построить на их основе более сложные контролы.