Visual2000 · Архив статей А.Колесова & О.Павловой

Создание приложения "Календарь наших дел" в среде VB 6.0

Часть 2.2

Андрей Колесов, Ольга Павлова

© Андрей Колесов, Ольга Павлова, 2000
Авторский вариант. Статья была опубликована c незначительной литературной правкой в журнале "КомпьютерПресс" N 05/2000, компакт-диск.


VII этап. Связываем приложение воедино

Теперь, когда у нас есть все компоненты будущего проекта, свяжем их в единое приложение. Обратите внимание, что сейчас наше приложение включает три группы компонентов, которые мы создавали и отлаживали автономно:

  1. модуль Module1 и формы frmMain, frmBrowser, frmAbout и frmSplash (единственная полезная функция такого приложения — доступ в Internet через простенький браузер — не имеет отношения к основной нашей задаче);
  2. форма frmRemindersSet, обеспечивающая полный набор функций по просмотру и редактированию базы данных Reminder.mdb;
  3. форма frmRemindersPopup, осуществляющая функции контроля за заданиями, которые занесены в базу данных Reminder.mdb, с помощью внешнего OCX-компонента Memos.

Шаг 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

В начало статьи

VIII этап. Решаем проблемы дистрибьюции

Мы создали отличную программу, однако она страдает одним серьезным внутренним недостатком. Чтобы убедиться в этом, сохраните проект, переименуйте каталог, где он находится (точнее, где находится база данных Reminder.mdb), загрузите проект еще раз и запустите программу на выполнение. Вы увидите, что она не будет работать из-за двух появившихся проблем.

Проблема 1. При запуске выдается целая серия сообщений "не найден файл базы данных", что соответствует действительности.

Прежде чем перейти к решению этой проблемы, нужно обратить внимание на два очень важных момента:

  1. Жесткая привязка приложения к абсолютным адресам имен используемых файлов является принципиальной ошибкой. (Если только речь не идет о какой-то хитрости. Впрочем, от таких "хитростей" больше всех страдает сам разработчик.) Поэтому использование стандартных диалогов для формирования адресов при привязке программных компонентов к файлам (как это сделано на шаге 16) является допустимым только при начальном формировании программного кода. Крайне желательно сразу же заменять статическое определение адреса файла на динамический, программный вариант.

  2. Особую проблему представляет необходимость привязки двух или более компонентов к одному источнику данных (как это реализовано в нашем случае для элементов управления ADO Data в формах frmRemindersSet и frmRemindersPopup). Для этого необходимо использовать механизм, который бы автоматически гарантировал тождественность адресов в разных компонентах. В частности, простое копирование строк ConnectionString из окна свойств одного элемента управления в другое (см. шаг 21) не решает эту проблему, так как в последующем, возможно, мы решим изменить данное свойство и забудем сделать это для другого компонента.

    Вариант назначения адреса файла для второго компонента через диалоговое окно 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. Это можно сделать двумя способами:

  1. В среде VB командой Project|Components откройте вкладку Controls окна Components и с помощью кнопки Browse добавьте файл Rmemos.OCX (этот файл, возможно, был в списке Controls и ранее, но его нужно "обновить").
  2. В среде Windows эта операция осуществляется с помощью системной утилиты RegSrv32.exe, запускаемой из командной строки.

Также следует помнить, что регистрация ActixeX-компонентов выполняется автоматически при их компиляции и создании автономно исполняемого файла.

Совет:

В начало статьи

Последний этап — стань Мастером!

Итак, подведем итоги:

  1. Вначале с помощью Application Wizard мы сформировали проект в составе пяти взаимосвязанных компонентов: модуля Module1 и формы frmMain, frmBrowser, frmAbout и frmSplash. (И проверили работоспособность этого приложения, хотя единственная его полезная функция — доступ в Internet через простенький браузер — не имеет отношения к основной нашей задаче.) Затем с помощью утилиты VisData мы создали базу данных Reminder (точнее — ее конфигурацию), а потом для работы с этой БД сделали форму frmReminders, используя Мастер DataForm.

  2. Далее мы начали писать программу "руками". Сначала была создана небольшая модернизация формы frmRemindersSet — мы заменили простое текстовое окно на более удобный для работы с датами вариант DateTimePicker. Мы проверили работу этого окна в автономном режиме, заполнив заодно нашу базу данных некоторым числом записей-напоминаний.

  3. Затем мы спроектировали окно frmRemindersPopup, предварительно создав пользовательский компонент Rmemos.OCX. В этом окне мы использовали новый полезный компонент DataRepeater для создания окна с прокруткой списка, строками которого являются визуальные элементы управления, связанные с базой данных. Написав программный код для этого окна, мы проверили его работоспособность, переводя в различные режимы ожидания и удаляя "выполненные дела".

  4. Связали все отдельные формы нашего приложения Reminders.vbp воедино, дописав всего две команды меню с очень простым кодом для главного меню.

  5. В завершение мы выполнили очень важную коррекцию приложения, реализовав динамическую привязку компонентов приложения к базе данных. Теперь его работоспособность никак не зависит от месторасположения на диске. Заодно вспомнили о том, как выполнять и отменять регистрацию ActiveX-компонентов.

Конечно, созданное нами приложение далеко от идеала. Для его практического применения понадобится провести еще много усовершенствований, например реализовать управление временем "спящего режима" или возможность выбора нужной базы данных во время работы.

Как мы убедились на своем опыте, использованные нами Мастера действительно помогают в создании приложения, но основная работа все же выполнялась "руками", причем исправления зачастую вносились прямо в готовый код. Получается, что чем сложнее решаемая нами задача, тем меньше наша потребность в применении готовых Мастеров.

Зачем же нужно изучать их работу? Оказывается, не столько для того, чтобы воспользоваться их готовым кодом, сколько для лучшего понимания общей логики и конкретных технических приемов разработки.

Короче говоря, чтобы самому стать МАСТЕРОМ.

В начало статьи