Visual2000 · Архив статей А.Колесова & О.Павловой
Андрей Колесов, Ольга Павлова
© Андрей Колесов, Ольга Павлова, 2000Часть 2.2 Доводка приложения до "профессионального" вида (окончание):
Теперь, когда у нас есть все компоненты будущего проекта, свяжем их в единое приложение. Обратите внимание, что сейчас наше приложение включает три группы компонентов, которые мы создавали и отлаживали автономно:
Шаг 28. Привязка двух последних форм к основному проекту очень легко реализуется через команды меню. Для этого вызовите редактор Menu Editor и вставьте новое меню между позициями "Просмотр" и "Справка", а затем установите Caption как "НашКалендарь", а Name — как mnuReminders. Добавьте к нему две команды с такими параметрами:
Caption Name ---------------------------------------- ФормированиеКалендаря mnuRemindersSet КонтрольНашихПланов mnuRemindersPopup
Запишите следующий код для обработки этих команд:
Private Sub mnuRemindersPopup_Click() ' показывает форму для контроля ' за записями-памятками Load frmRemindersPopup frmRemindersPopup.Show End Sub Private Sub mnuRemindersSet_Click() ' показывает форму для ввода данных frmRemindersSet.Show vbModal End Sub
Теперь установите (уже окончательно!) имя Sub Main в списке Startup Objects окна Project Properties|General и запустите наше приложение на выполнение. Убедитесь, что оно работает так, как и было задумано (рис. 28). После этого можно создать исполняемый модуль проекта Reminder.EXE.
Рис. 28
Мы создали отличную программу, однако она страдает одним серьезным внутренним недостатком. Чтобы убедиться в этом, сохраните проект, переименуйте каталог, где он находится (точнее, где находится база данных Reminder.mdb), загрузите проект еще раз и запустите программу на выполнение. Вы увидите, что она не будет работать из-за двух появившихся проблем.
Проблема 1. При запуске выдается целая серия сообщений "не найден файл базы данных", что соответствует действительности.
Прежде чем перейти к решению этой проблемы, нужно обратить внимание на два очень важных момента:
Вариант назначения адреса файла для второго компонента через диалоговое окно Open заключает в себе дополнительную опасность того, что пользователь может даже не заметить, что случайно выбрал другой файл (это довольно часто случается при отладке, когда существует несколько вариантов похожих баз данных с одинаковыми именами, но в разных каталогах).
Мы не выполнили эти два условия по ходу разработки программы только потому, чтобы сейчас обратить ваше внимание на эту проблему. Ее решение достаточно простое — нужно программным образом осуществлять привязку приложения к базе данных во время выполнения приложения.
Мы предлагаем следующий вариант: переменная MyConnectionString, которая хранит строку для связи с базой данный Reminder.mdb, будет описана как глобальная в модуле Module1.bas, и ее содержимое будет формироваться там же. Определение свойств элементов управления для связи с базой данных станет выполняться программно каждый раз при загрузке соответствующей формы.
Шаг 29. Принимая во внимание, что файл нашей базы данных находится в одном каталоге с проектом, мы должны добавить такой код в модуль Module1.bas:
Public MyConnectionString As String Sub Main() ' Этот код можно включить в самое начало процедуры: ' описание строки соединения с базой данных MyConnectionString = _ "Provider=Microsoft.Jet.OLEDB.3.51;" & _ "Persist Security Info=False;" & _ "Data Source=" & App.Path & "\Reminder.mdb" ... End Sub
Шаг 30. Проблема программной привязки формы к источнику данных заключается в том, что здесь недостаточно провести замену только одного свойства ConnectionString у элемента управления ADO Data — нам необходимо откорректировать все свойства компонентов, связанные с этим источником данных. Для этого нужно поместить следующий код в процедуру Form_Load формы frmRemindersSet:
' программная настройка компонентов формы на ' связь с источником данных With datPrimaryRS ' привязка ADO Data .ConnectionString = MyConnectionString .RecordSource = "Select RemindTime, " & _ "RemindMemo from Reminder Order by RemindTime" End With ' привязка элемента DateTimePicker Set dtpRemindTime.DataSource = datPrimaryRS dtpRemindTime.DataField = "RemindTime" ' привязка TextBox Set txtRemindMemo.DataSource = datPrimaryRS txtRemindMemo.DataField = "RemindMemo"
Таким образом получается, что нам нужно продублировать установки, созданные с помощью оконного интерфейса в среде VB. Более того, для корректной работы формы необходимо очистить все установки данных свойств у соответствующих элементов управления в окне Properties Window. То есть требуется, чтобы в исходном состоянии поля ConnectionString и RecordSource для datRrimaryRS и поля DataSource и DataField для dtrRemindTime и txtREmindMemo были пустыми.
Для формы frmRemindersPopup поместите следующий код в самое начало процедуры Form_Load:
With Adodc1 'элемент ADO Data .ConnectionString = MyConnectionString1 .RecordSource = "Select * from Reminder " & _ "Order By RemindTime Desc"; End With ' привязка элемента DataRepeater Set DataRepeater1.DataSource = Adodc1
При этом следует очистить все переопределяемые поля элементов управления. Но обратите внимание: в данном случае допускается использование установленных нами в диалоговом режиме параметров RepeaterBindings для элемента управления DataRepeater (см. шаг 22). Однако при желании эти установки можно также осуществить программным образом (предварительно очистив соответствующие параметры RepeaterBindings, см. там же рис. 24), для чего необходимо добавить следующий код:
DataRepeater1.RepeaterBindings.Add "RemindTime", _ "RemindTime" DataRepeater1.RepeaterBindings.Add "RemindMemo", _ "RemindMemo" DataRepeater1.RepeaterBindings.Add "DeleteMe", _ "DeleteMe"
Запустите наше приложение на выполнение и убедитесь, что проблема с привязкой к базе данных (при условии, что этот файл находится в том же каталоге, что и сам проект) полностью решена.
Проблема 2. Пропала связь элемента управления DataRepeater с пользовательским компонентом Rmemos.OCX.
Действительно, даже при работе в среде VB вы увидите, что элемент управления заполнен простым серым полем, как это было в начальный момент его установки до привязки с используемым в нем компонентом. Причина этого понятна — связь с компонентом Rmemos.OCX осуществляется через его регистрацию в Реестре Windows. Мы изменили местоположение файла, и связь оказалась утерянной.
В данном случае можно только сожалеть, что VB не выдает никакой диагностики относительно того, что он не может обнаружить нужный ему компонент (как в случае с ошибкой в адресе источника данных). Мало того, разработчик может быть введен в заблуждение тем, что компонент Rmemos.Memos находится в списке зарегистрированных элементов управления в списке поля RepeatedControlName и, более того, — указан там в качестве актуальной связи (рис. 29).
Рис. 29
Чтобы убедиться, что эта информация неверна, выполните следующие действия. Выберите для свойства RepeatedControlName какой-нибудь другой компонент, например RichTextBox. А затем попробуйте опять произвести связку с Rmemos.Memos — появится сообщение о невозможности выполнения данной операции.
Для решения данной проблемы, нужно провести перерегистрацию файла Rmemos.OCX. Это можно сделать двумя способами:
Также следует помнить, что регистрация ActixeX-компонентов выполняется автоматически при их компиляции и создании автономно исполняемого файла.
Совет:
Отведите для хранения всех готовых ActiveX-компонентов, которые
вы создаете сами или переписываете откуда-то автономно, отдельный
каталог. Только не используйте для этого "мусорный ящик",
называемый системным каталогом Windows, — создайте что-нибудь
вроде C:/MyActiveXComponents. Перепишите туда саму утилиту
RegSrv32.exe. Далее, переписывая в этот каталог новые
ActiveX-компоненты (OCX и DLL), можно будет сразу выполнять их
регистрацию:
RegSrv32.exe MyNew.OCX
Если вы хотите удалить ненужные компоненты, сначала отмените их регистрацию в Реестре:
RegSrv32.exe /i MyOld.OCX
и только потом физически удаляйте файл с диска. Помните, что только таким образом можно удалить ненужные компоненты из списка Components|Controls в среде VB.
Итак, подведем итоги:
Конечно, созданное нами приложение далеко от идеала. Для его практического применения понадобится провести еще много усовершенствований, например реализовать управление временем "спящего режима" или возможность выбора нужной базы данных во время работы.
Как мы убедились на своем опыте, использованные нами Мастера действительно помогают в создании приложения, но основная работа все же выполнялась "руками", причем исправления зачастую вносились прямо в готовый код. Получается, что чем сложнее решаемая нами задача, тем меньше наша потребность в применении готовых Мастеров.
Зачем же нужно изучать их работу? Оказывается, не столько для того, чтобы воспользоваться их готовым кодом, сколько для лучшего понимания общей логики и конкретных технических приемов разработки.
Короче говоря, чтобы самому стать МАСТЕРОМ.