Приложение
Вот на какие моменты при решении этой задачи следует обратить внимание:
- Спроектированная мной форма не является модальной. Это не является принципиальным в поставленной задаче, тем не менее, может быть важным, поскольку позволяет произвести изменение формы вне самой формы. О модальности форм следовало бы поговорить в основном тексте книги, но я этого, к сожалению, не сделал. Поэтому поговорим об этом сейчас. Формы Office 2000 обладает новым важным булевым свойством Modal, значение которого можно установить в момент проектирования. Если это значение равно True, то окно формы является модальным и его нельзя покинуть до закрытия. Если значение - False, то можно покинуть форму, поработать с документом, нажимать, например, другие кнопки в документе, модифицируя, возможно, саму форму. Заметим, что в Office 97 создать не модальное окно можно было только, используя объекты Balloon, входящие в состав объекта Assistant. Теперь сделан важный шаг в правильном направлении, - центральный объект интерфейса - UserForm получил возможность работать в немодальном окне. Главное, что для программиста это не требует никаких усилий, достаточно изменить значение одного свойства. Замечу, что в С++, по крайней мере, в версии 4 работа с немодальными окнами требовала профессиональных знаний, в частности, умения посылать сообщения операционной системе. Но вернемся к нашей задаче.
- Элементы управления достаточно просто программным путем вставляются в форму в период выполнения программы, и я об этом рассказывал в главах, посвященных проектированию интерфейса. У объекта Form есть коллекция Controls, у которой есть метод Add, позволяющий добавить любой из элементов управления. В нашем примере мы уже спроектировали форму с двумя элементами управления - командной кнопкой и окном редактирования. В обработчиках события Click командной кнопки самой формы и командной кнопки "Add Controls to Form", встроенной в тестовый документ, вызывается процедура AddControls, которая добавляет в форму еще пару таких же элементов управления. Заметьте, поскольку наша форма не является модальной, то нажимать командные кнопки можно как в самой форме, так и вне формы. Вот текст процедуры, добавляющей в форму элементы управления:
Public Sub AddControls() 'Эта процедура добавляет командную кнопку и окно редактирования в форму With UserForm1 'Добавляем окно редактирования Set Mycmd = .Controls.Add("Forms.TextBox.1", "ProgramBox", True) Mycmd.Left = .TextBox1.Left Mycmd.Top = .TextBox1.Top + 100 Mycmd.Width = .TextBox1.Width Mycmd.Height = .TextBox1.Height Mycmd.Text = "New Control - " & Mycmd.Name 'Добавляем командную кнопку Set Mycmd = .Controls.Add("Forms.CommandButton.1", "ProgramButton", True) Mycmd.Left = .CommandButton1.Left Mycmd.Top = .CommandButton1.Top + 100 Mycmd.Width = .CommandButton1.Width Mycmd.Height = .CommandButton1.Height Mycmd.Caption = "ProgramButton" End With End Sub
- Вот как выглядит форма, после того как была нажата кнопка "Add Controls to Form" и ее обработчик вызвал процедуру AddControls:
- Добавленные таким путем элементы управления живут в форме только до ее закрытия. Но, заметьте, если скрыть форму, вызвав метод Hide, то при повторном ее открытии элементы управления сохраняются.
- Перейдем теперь непосредственно к ответу на первый поставленный вопрос. Для его решения потребуются средства, ранее не упоминавшиеся в книге. Нам понадобятся объекты класса VBComponent - компоненты VB-проекта (объекта класса VBProject ). Чтобы можно было с ними работать, необходимо включить дополнительную ссылку на библиотеку VBIDE (Visual Basic Extensibility). Ну, а теперь отвечаю конкретно на первый поставленный вопрос. Можно программно добавить элементы управления так, чтобы они сохранялись в форме точно также как сохраняются элементы, созданные в период проектирования. Для этого нужно работать с объектом, представляющим форму в режиме проектирования, используя свойство Designer объекта VBComponent. Вот как это делается:
Public Sub AddDesignControls() 'Эта процедура добавляет командную кнопку и окно редактирования в форму Dim MyForm As UserForm 'Создаем форму этапа проектирования Set MyForm = ActiveDocument.VBProject.VBComponents("UserForm1").Designer With MyForm 'Добавляем окно редактирования Set Mycmd = .Controls.Add("Forms.TextBox.1", "ProgramBox", True) Mycmd.Left = .TextBox1.Left Mycmd.Top = .TextBox1.Top + 100 Mycmd.Width = .TextBox1.Width Mycmd.Height = .TextBox1.Height Mycmd.Text = "New Control - " & Mycmd.Name 'Добавляем командную кнопку Set Mycmd = .Controls.Add("Forms.CommandButton.1", "ProgramButton", True) Mycmd.Left = .CommandButton1.Left Mycmd.Top = .CommandButton1.Top + 100 Mycmd.Width = .CommandButton1.Width Mycmd.Height = .CommandButton1.Height Mycmd.Caption = "DesignButton" End With 'Удаляем командную кнопку, вызывающую эту процедуру. 'Эта кнопка может работать лишь раз, по крайней мере, 'пока в режиме проектирования не будут удалены добавленные элементы. 'Заметьте, кнопку можно только удалить, но нельзя сделать ее невидимой. ActiveDocument.InlineShapes(4).Delete End Sub
Обратите внимание, к нашей форме, рассматриваемой как объект класса VBComponent, мы добираемся через свойство VBProject нашего документа. Имея форму, в последний момент вызываем Designer, который и возвращает форму периода проектирования. Теперь добавление элементов управления будет постоянным. Само добавление делается, как и ранее, никаких изменений в этом процессе здесь нет.
Однако есть некоторые естественные ограничения, на которые следует обратить внимание. Процедура AddDesignControls, добавляющая элементы периода проектирования, должна вызываться при закрытой форме и только один раз. Поэтому в конце этой процедуры добавлен текст, удаляющий из тестового документа командную кнопку (объект класса InlineShape ), обработчик которой вызывал процедуру AddDesignControls.
Вот как выглядит форма, открытая после окончания работы этой процедуры: