Реализация командного переключателя в Visual Basic
По роду деятельности мне постоянно приходится заниматся реализацией
пользовательского интерфейса. Надо сказать, что все Windows приложения
строятся обычно по одному шаблону - главное окно, меню, панель инструментов
(toolbar), контекстное меню. Такой подход к построению интерфейса подробно
описан и даже стандартизирован.
Для удобства работы делают так, что каждая из команд может быть вызвана из
нескольких мест: основное меню, контекстное меню и т.д. В зависимости от
текущего состояния команда может быть разрешена/запрещена (enabled/disabled),
отмечена (checked) или даже может считаться командой по умолчанию (default).
Как реализовать такой подход в приложении на Visual Basic? Проблема здесь не
только в том что одна и та же команда вызывается из нескольких мест. Для
каждой команды нужно еще и отслеживать ее состояние. Здесь излагается подход к
решению этой проблемы. Такую схему я с успехом использую во многих своих
приложениях.
Итак, источники команд - это Menu Bar, Toolbar(s), Context Menu и другие
controls. Введем понятие идентификатор команды (Command ID).
Идентификатор команды - это строка, содержащая только символы a-z, A-Z (регистр
важен). В сущности, можно было бы использовать и числовые константы, но строка
удобнее для хранения ее в свойствах Tag различных элементов управления.
В сложной команде идентификатор и параметр разделяются двоеточием:
"CommandID:Parameter". Примером сложной команды может служить команда
сортировки - "SortBy:Name".
Команды можно группировать в множества команд, которые легко описать строкой
команд, перечисленных через запятую: "Cmd1,Cmd2,Cmd3". Такая строка легко
разделяется на отдельные команды функцией Split.
Обработчики Click пунктов меню, кнопок панели инструментов и т.п. - все
содержат только вызов процедуры DoCommand с параметром - ID команды. Тем
самым, вся обработка команд сведена в одно место.
Процедура DoCommand вызывает по команде соответствующее ей действие:
Private Sub DoCommand(ByVal sID as String)
Select Case sID
Case "Exit": Unload Me
Case "About": FormAbout.Show
Case "HelpContents": DoShowHelpContents
End Select
End Sub
Для определения свойств команды в соответствием с текущим состоянием
заводим пару булевых функций:
IsCommandEnabled(sID) As Boolean Определение разрешенности команды
IsCommandChecked(sID) As Boolean Определение checked команды
Еще нужна процедура для обновления свойств контролов в соответствии с текущим
состоянием приложения:
Private Sub UpdateEnable()
В ней свойства Enabled и Checked выставляются по результату IsCommandEnabled и
IsCommandChecked. UpdateEnable должна вызываться в начале работы программы и
в процедурах-действиях - при изменении текущего состояния программы.
Все изменения состояния программы полезно также свести в несколько процедур с
названием SetXxx (например, SetSortOrder(sFieldName)). В конце каждой из этих
процедур вызывается UpdateEnable, приводя в соответствие состояние программы и
состояние контролов команд.
Тем самым, команда теперь выполняется так:
человек вызывает команду (например, File|Exit)
вызывается событие (например, mnuFileExit_Click)
вызывается DoCommand
вызывается процедура действия, производится действие
вызывается процедура изменения состояния SetXxx
вызывается UpdateEnable, обновляется вид контролов.
Для тех, у кого есть любые вопросы, имеюшие отношение к тематике Visual
Basic, хочу порекомендовать место, где на них можно получить ответ.
Причем в течении совершенно разумного и небольшего промежутка времени
- от нескольких часов до нескольких дней. Место это - конференция RU.Visual.Basic,
расположенная
на сайте Visual Basic на русском
Для сомневающихся в эффективности такого метода получения ответов, информирую,
что за декабрь месяц среднее ежедневное количество сообщений составлило
65 - общее за месяц - 2031
Хочу поставить в известность всех
подписчиков этого листа - лист создается в html, а потом автоматом на
Ситикоте из него создается текстовый вариант. Так что, если вы, по ошибке,
подписались на текстовую версию - рекомендую изменить этот параметр, так
как за качество конвертации я не отвечаю, а создавать отдельную версию
у меня не хватает времени. Сорри.