Автоматическое изменение размеров форм |
Автор Юрий Шерман | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
27.01.2004 г. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
Автоматическое изменение размеров форм1.Постановка задачиСама задача расчета размера форм не нова. Она описывается и решается, например, в [1]. Можно привести примеры сайтов (например [2], [3]), где постановка задачи и её решения другие. Однако нигде нет достаточно полной постановки задачи. Более полный вариант, с моей точки зрения, должен выглядеть так. Программист или группа программистов, разрабатывая проект на Access, использует для создания форм обязательно одинаковое разрешение экрана. Пояснять это, очевидно, не требуется. Однако, попав к конечному пользователю, проект исполняется, вообще говоря, при других разрешениях. При этом внешний вид форм может сильно измениться: они могут визуально сильно уменьшиться, вплоть до неразличимости текстов, или увеличиться, выходя за рамки окна Access. Отсюда первая задача: видимые размеры форм и их элементов должны изменяться пропорционально изменению разрешения экранов. Так как видимые размеры зависят не только от разрешения экрана, но и от DPI (мелкий, крупный и т.д. шрифт), от конкретных свойств видеоадаптера, то при решении первой задачи должно учитываться и это. Однако этого мало. При больших разрешениях экрана (типа 1600 х ….), характерных для больших мониторов, пользователи часто используют для отображения окна Access не весь экран, а только часть его. При этом они в любой момент могут изменить размер окна Access. Потому возникает вторая задача: видимые размеры форм и их элементов должны так же изменяться пропорционально изменению окна Access. Этот момент, видимо, упущен во всех постановках. Далее, пользователю может не понравиться размер или положение формы на экране, которое предусмотрено программистом. Следует дать ему возможность изменить эти характеристики. А модулю расчета размеров форм необходимо запомнить установленные характеристики формы и воспроизвести их при следующей загрузке формы, пропорционально изменив их, если загрузка произойдет при других внешних условиях (например, при другом разрешении экрана). Это третья задача, которую необходимо решить. Теперь следует уточнить, что понимается под пропорциональностью. Во всех известных мне постановках понимается следующее: если, например, разрешение экрана требует увеличения по ширине на X %, а по высоте на Y %, то это и следует сделать как с формой, так и со всеми её элементами. То есть пропорциональность здесь двойная: независимая по ширине и по высоте. Назовем это линейным режимом изменений формы. Хотя скорее его лучше назвать резиновым - за какую сторону потянем форму, то так же поползут и размеры элементов формы. Однако линейный режим очевидно противоречит интересам пользователя. Пользователь вынужден подгонять размеры формы так, чтобы размеры элементов выглядели нормально. А точнее так, как сделал их программист. Ведь он думал и выверял для каждого элемента формы соотношение ширины и высоты каждого элемента. Наиболее естественно при изменении размеров формы сохранить это соотношение, избавив пользователя от ненужной работы. Назовем изменение формы с сохранением соотношений ширин и высот элементов, заданных программистом, реально пропорциональным режимом или просто пропорциональным режимом. Такое понимание пропорциональности мне не встречалось. Реализация реально пропорционального режима изменения форм является четвертой задачей. Особое внимание следует уделить линейным формам. При увеличении формы по высоте Access сам по себе просто добавляет новые строки. Эту реакцию следует сохранить и при применении пропорционального режима. Однако увеличение по ширине должно не добавлять пустое пространство в форму, как это делает Access, а пропорционально увеличивать элементы формы. Далее следует устанавливать (при возможности) такие размеры формы, чтобы последняя видимая строка не разрезалась границей формы. Это пятая задача. Работа с формами в режиме таблицы по тем принципам, что и с формами в режиме форм, является шестой задачей. В [1] эта задача объявлена неразрешимой. Однако это не так. Далее следует обеспечить обработку всплывающих форм и произвольно вложенных субформ. Естественно, по тем же принципам. Это седьмая и восьмая задачи. Девятая задача – максимальная простота применения модуля расчета форм. Как в новых, так и в старых задачах. 2. Общее описание работы модуля ResizeFormМодуль реально разрабатывался и применялся в практических задачах начиная с 1998 г. И только в конце 2003 г. он, кажется, достиг состояния, соответствующего постановке задачи, данной в п.1. Модуль написан в Access-97, и использует только явно описанные возможности. Версия для Access-2002 получена преобразованием из версии для Access-97. Сам модуль находится в базе ResForm2002.mde. Кроме него базе имеется общий модуль, обеспечивающий функции отключения/включения модуля расчета размеров форм, очистку памяти от запомненных характеристик форм и некоторые другие функции. Решение первой задачи (установки монитора) использует те же методы, которые применяются в [1]. Для решения второй задачи (учет размеров окна Access) применен метод считывания его характеристик по таймеру, так как изменение его размеров никаких событий не порождает. Так же по таймеру обнаруживается изменение размеров и положения формы. Для хранения характеристик форм, установленных пользователем, используются Properties базы ResForm2002.mde. Это позволило обойтись без использования таблиц, а так же без записей в основную базу или в системные области Windows. Методы решения задач четыре-восемь оригинальны, и пока не описываются. Работа с формами (субформами) в виде таблиц имеет свои особенности. Дело в том, что пользователь имеет дополнительные возможности: изменить высоту строки, размер шрифта, размер столбцов, скрыть или переставить их потому как ResForm в демо не учитывает скрытия столбцов. Эти характеристики таблицы модуль запоминает и воспроизводит из при следующем вызове. То есть фактически запоминаются индивидуальные настройки таблиц для каждого компьютера, что обычно делается при помощи специальных программ. При расчете размеров используются все характеристики формы, установленные программистом, включая параметр AutoCenter, который игнорируется в [1]. Допускается загрузка формы в максимизированном состоянии. Основной режим (по умолчанию) расчета размеров форм – пропорциональный. Однако для возможности сравнения с другими программами реализован и линейный режим. Модуль перехватывает только одно событие формы (выгрузка) для определения момента записи характеристик формы. Дополнительные возможности. Если программист намеренно создал форму, выходящую за границы окна Access по вертикали или по горизонтали, то модуль успешно обработает и эту ситуацию.
О качестве решения девятой задачи (удобство использования) можно судить на основе анализа демонстрационного примера Demo2002.mdb, и данного ниже описания программирования работы с модулем. 3. Критический обзор свойств модулей FormResize, ControlResize, SectionResize, предложенных в [1] для расчета размеров форм.Расчет размеров форм производится только в линейном режиме, что, как указано выше, весьма неудобно для пользователей – то есть четвертая задача не решена. Первая задача решена. Вторая задача (учет размеров окна Access) не решена. Третья задача(учет изменений характеристик форм, сделанных пользователем) решена не полностью – нет хранения измененных характеристик форм и учета этих характеристик при открытии форм. Пятая задача не ставилась и не решалась. Шестая задача объявлена неразрешимой (стр. 512). Седьмая и восьмая задачи решены. Девятая задача решена, за исключением работы с параметром формы AutoCenter. Работу модулей можно посмотреть на примере базы Getz2002.mdb. В работе авторов имеется, с моей точки зрения, серьезная логическая ошибка в расчете коэффициентов изменения элементов формы. Дело в том, что, получив коэффициенты в качестве результатов решения первой задачи, авторы применяют их как к форме, так и к ее элементам. Сами коэффициенты вычисляются с очень высокой точностью, что является специальной заботой авторов. Однако далее совершенно не учитывается то обстоятельство, что в форме, помимо элементов с изменяемыми размерами, есть неизменяемые и отнюдь не маленькие. По ширине это: размеры области границы, области выделения, вертикальной линейки прокрутки. По высоте: область границы, горизонтальная линейка прокрутки, панель навигации. Легко построить пример, показывающий, что отсутствие учета этих элементов приводит к существенным искажениям вида формы. Но разницу можно увидеть на примере формы PeopleList. При вызове её из базы Demo2002.mdb, которую обслуживает модуль ResizeForm, горизонтальной полосы прокрутки нет. А при вызове из Getz2002.mdb она появляется. То есть во втором случае рассчитанные размеры окна формы меньше ширины формы. Исходные формы идентичны (за исключением модуля формы). Задача учета размеров неизменяемых элементов оказывается весьма не простой, так как: В модуле ResizeForm эта задача решена.
Мелкие замечания.Для построения системы хранения текущей информации о форме авторами используется множество экземпляров модулей классов (например, для каждого элемента формы), строятся различные коллекции. Возможно это сделано в учебных целях, так как массивов вполне достаточно для организации хранения текущей информации. Но в результате программа авторов работает существенно медленнее ResizeForm, занимает больше оперативной памяти. Центрирование форм авторы выполняют только при программном назначении свойству CenterOnOpen значения True. Однако они выполняют его не так как Access. При центрировании по вертикали Access делит свободную часть окна в соотношении 1 : 2. То есть верхний отступ меньше нижнего. Так действительно центрированная форма смотрится лучше. Авторы размещают форму, деля свободную часть в соотношении 1 : 1. То есть действительно по центру. А вид хуже. При расчете групповых элементов (вкладки, переключатели) авторы используют итерационные методы, что так же не ускоряет работу. (Вполне возможно использование только прямых методов). Работа авторов принципиально не переносима в Access-97. 4. Программа Новикова [2] и продаваемая программа [3].Программа Новикова решает только первую задачу. И то только частично. В ней имеется та же логическая ошибка, что и в [1]. В продаваемой программе полностью закрыт текст даже демонстрационного примера. Поэтому серьезно ее проанализировать невозможно. Лучше ее посмотреть. Отмечу, что в программе реализован только линейный режим, она не реагирует на изменение окна Access, и при некоторых изменениях размеров формы в демонстрационном примере дает программную ошибку. 5. Демонстрационный пример и применение ResizeForm в других задачах.Вообще говоря, разработанный модуль ResizeForm предназначен для продажи. Но конкретный модуль ResizeForm, который находится в демонстрационном примере в базе ResForm2002.mde, можно бесплатно использовать в любой задаче, написанной на А-2002, если она разрабатывалась при следующих установках: - разрешение экрана 800х600 - мелкий шрифт (DPI = 96) - на рабочем столе панель задач установлена (не скрывается), других панелей нет - окно Access максимизировано - в окне Access имеются две панели инструментов и строка состояния 5.1 Подготовка задачи к применению модуля.Подготовка сводится к замене всех шрифтов на тип TrueType. Только этот тип допускает более-менее точное масштабирование. К сожалению, по умолчанию в Access установлен шрифт MS Sans Serif, который не является типом ТТ. Его везде следует заменить на тип ТТ. Рекомендуемые шрифты: Arial, Times New Roman, Courier, Tahoma. Замену шрифтов можно выполнить программным путем. Вот текст программы замены шрифтов:
Рекомендация 1. Поля надписей следует делать с запасом. Дело не только в том, что шрифты могут иметь только целочисленные размеры. При изменении размера шрифта конкретного текста соотношение длина строки/высота строки меняется в зависимости и от конкретного шрифта, и от содержания строки, если шрифт не равноширинный. Рекомендация 2. При разработке задачи используйте наименьшее возможное разрешение экрана. Дело в том, что при работе задачи на мониторе с большим разрешением, чем было использовано при разработке, формы выглядят достаточно хорошо. А при работе на мониторе с меньшим разрешением внешний вид форм ухудшается. И чем больше разница, тем сильнее. 5.2 ПрограммированиеПоместите базу ResForm2002.mde (имя базы можно изменить) в тот же каталог, в котором находится ваш проект. Установите ссылку из вашего проекта на базу ResForm2002.mde. Теперь модуль ResizeForm доступен для ваших программ. Хранение в одном каталоге сохранит работоспособность вашего проекта при перемещениях. Подчеркну, что каждому экземпляру вашего проекта должен соответствовать только одна база ResForm2002.mde. Далее следует обеспечить для каждой формы расчет ее размеров при загрузке и пересчет размеров при изменении пользователем характеристик формы. При исполнении второй части используется таймер. Все программирование следует делать только для основной формы. Для вложенных форм этого не требуется. 5.2.1 Расчет размеров формы при загрузкеВ общую часть описания модуля формы внесите строку:
В этой переменной будет храниться ссылка на конкретный экземпляр модуля класса ResizeForm, обслуживающий именно эту форму. При закрытии формы Access автоматически удалит связанный с ней модуль. В обработку события формы «открытие» или «загрузка» (безразлично) внесите две строки:
Первая строка создает экземпляр модуля, связанный с формой. Вторая строка выполняет расчет размеров формы при загрузке. 5.2.2 Пересчет размеров формы по таймеру.Выполнение пересчета вызывается одной строкой в программе обработки события "таймер": ResForm.SetFormSizeTimer Интервал таймера рекомендуется устанавливать равным 500 (половина секунды.). В демонстрационном примере каждая форма оснащена своим таймером. Это сделано для удобства демонстрации: формы можно вызывать независимо друг от друга. В практической задаче гораздо лучше применять один таймер, связанный с постоянно загруженной формой (обычно загружаемой первой и невидимой). Для реализации такого подхода следует переменную ResForm в общем описании модулей форм объявить как Public. Тогда программа обработки события «таймер» первой формы будет выглядеть так:
Вызов SetFormSizeTimer пересчитывает размер как видимой формы, так и невидимой. Для минимизации обращений к расчету форм можно использовать значение, возвращаемое функцией SetFormSizeTimer. Оно равно False, если форма не изменилась. Предшествующие формы как будто можно не рассчитывать. На этом программирование заканчивается. 5.3 Свойства и методы модуля ResizeForm
5.5 Общие функции общего модуля ResizeFormMainВсе перечисленные ниже функции используются только при корректировке программ, так как в это время модуль расчета форм работать не должен. Форму, открытую в конструкторе, модуль никогда не изменяет. При программировании следует обнулить интервал таймера. Работа таймерной программы мешает вводу текстов на VBA.
Загрузка демонстрационных примеров.http://hiprog.com/index.php?option=com_content&task=view&id=715&Itemid=35 Список ссылок.
Просмотров: 32204
|