Задача: динамически создать ActiveX контрол на форме при загрузке (VB.Net)
Беру свой старый добрый ActiveX контрол, цепляю к оболочке. Оболочка честно генерит для контрола враппер через AxHost. На событии Form_Load присваиваю переменной новую инстанцию контрола и добавляю переменную в коллекцию Form.Contols.
Если ничего дальше не делать (работая только с наследными от AxHost пропертями — размер, положение), то контрол нормально появляется на форме. Но нафиг мне он пустой нужен? Правильно, пытаюсь вызвать свойства или методы (не наследные) этого контрола. На любой вызов получаю исключение AxHost.InvalidActiveXStateException, т.е. якобы объект находится в непонятном состоянии. Если необходимые мне вызовы повесить на кнопку (т.е. вызвать после отработки/возврата из Form_Load), то контрол совершенно чудно работает.
Способа "активировать" или перевести в другое "состояние" созданный элемент я не нашел. Попытки вызывать метод AxHost.CreateControl (который якобы принудительно создает контрол) тоже результата не дают.
Что тут можно еще придумать?
23.12.03 18:12: Перенесено модератором из '.NET' — AVK
Re: Динамическая генерация ActiveX на форме
От:
Аноним
Дата:
09.07.03 13:01
Оценка:
Здравствуйте, DAA, Вы писали:
DAA>Способа "активировать" или перевести в другое "состояние" созданный элемент я не нашел. Попытки вызывать метод AxHost.CreateControl (который якобы принудительно создает контрол) тоже результата не дают.
попробуй по reflection вызвать protected метод AttachInterfaces. Это изменит состояние Ax.
Здравствуйте, AndrewVK, Вы писали:
AVK>Вобще то дизайнер должен был вставить в код инициализации что то вроде этого:
AVK>this.axWebBrowser1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axWebBrowser1.OcxState")));
Да, дизайнер вставлет этот код, если я помещаю контрол на форму в дизайнере:
Позор мне! Не догадался помотреть, что за код инициализации вставляет система для контролов, сгенеренных вручную.
Итого, для динамической генерации ActiveX контрола нужно:
Определить объектную переменную
Friend WithEvents ctl As AxCtl.AxCtl
Создать экземпляр
ctl = New AxCtl.AxCtl
Добавить экземпляр контрола в коллекцию
Me.Controls.Add(ctl)
До вызова любого ненаследемого от AxHost метода выполнить следующий код:
Здравствуйте, DAA, Вы писали:
DAA>CType(Me.ctl, System.ComponentModel.ISupportInitialize).BeginInit() DAA>CType(Me.ctl, System.ComponentModel.ISupportInitialize).EndInit()
DAA>Видимо, этот код выполняет переопределенные AxHost-ом методы какой-то инициализации.
Этот код скорее всего выполняет вызов IPersistXxx::InitNew инициализирующий контрол и делает контрол UI-активным.
... << RSDN@Home 1.1 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, DAA, Вы писали:
DAA>>CType(Me.ctl, System.ComponentModel.ISupportInitialize).BeginInit() DAA>>CType(Me.ctl, System.ComponentModel.ISupportInitialize).EndInit()
DAA>>Видимо, этот код выполняет переопределенные AxHost-ом методы какой-то инициализации.
VD>Этот код скорее всего выполняет вызов IPersistXxx::InitNew инициализирующий контрол и делает контрол UI-активным.
Ввиду того, что никто не опубликовал ответ на заданный вопрос полностью то приведу собственное решение проблемы (честно слямзенное у MS). Может кому сэкономит полчаса
public void InitAX()
{
// необходимо создать ActiveX FlexGrid7
// Создаем wrapper при помощи AxImp.exe, далее..
// ФУНКЦИЯ ИНИЦИАЛИЗАЦИИ...
DocumentGrid = new AxVSFlex7.AxVSFlexGrid();
// несмотря на то, что wrapper создан сам ActiveX еще не создан.
// работать с методами ActiveX'а можно будет после создания - перехватываем событие создания
DocumentGrid.HandleCreated += new EventHandler(DocumentGrid_HandleCreated);
DocumentGrid.BeginInit();
DocumentGrid.Anchor = AnchorStyles.Top | AnchorStyles.Left;
DocumentGrid.Dock = DockStyle.Fill;
this.Controls.Add( DocumentGrid );
DocumentGrid.EndInit();
}
private void DocumentGrid_HandleCreated(object sender, EventArgs e)
{
// после перехвата этого события можно работать не опасаясь выброса
// исключения о неправильном состоянии ActiveX
DocumentGrid.OutlineBar = VSFlex7.OutlineBarSettings.flexOutlineBarSimple;
DocumentGrid.Cols = 11;
DocumentGrid.Rows = 40;
//....
}
Классическая ошибка, которую совершают проектировщики абсолютно надежных систем, — недооценка изобретательности клинических идиотов.
Здравствуйте, kly, Вы писали:
kly>Здравствуйте, VladD2, Вы писали:
VD>>Здравствуйте, DAA, Вы писали:
DAA>>>CType(Me.ctl, System.ComponentModel.ISupportInitialize).BeginInit() DAA>>>CType(Me.ctl, System.ComponentModel.ISupportInitialize).EndInit()
DAA>>>Видимо, этот код выполняет переопределенные AxHost-ом методы какой-то инициализации.
VD>>Этот код скорее всего выполняет вызов IPersistXxx::InitNew инициализирующий контрол и делает контрол UI-активным.
kly>Ввиду того, что никто не опубликовал ответ на заданный вопрос полностью то приведу собственное решение проблемы (честно слямзенное у MS). Может кому сэкономит полчаса
kly>
kly>public void InitAX()
kly>{
kly> // необходимо создать ActiveX FlexGrid7
kly> // Создаем wrapper при помощи AxImp.exe, далее..
kly> // ФУНКЦИЯ ИНИЦИАЛИЗАЦИИ...
kly> DocumentGrid = new AxVSFlex7.AxVSFlexGrid();
kly> // несмотря на то, что wrapper создан сам ActiveX еще не создан.
kly> // работать с методами ActiveX'а можно будет после создания - перехватываем событие создания
kly> DocumentGrid.HandleCreated += new EventHandler(DocumentGrid_HandleCreated);
kly> DocumentGrid.BeginInit();
kly> DocumentGrid.Anchor = AnchorStyles.Top | AnchorStyles.Left;
kly> DocumentGrid.Dock = DockStyle.Fill;
kly> this.Controls.Add( DocumentGrid );
kly> DocumentGrid.EndInit();
kly>}
kly>private void DocumentGrid_HandleCreated(object sender, EventArgs e)
kly>{
kly> // после перехвата этого события можно работать не опасаясь выброса
kly> // исключения о неправильном состоянии ActiveX
kly> DocumentGrid.OutlineBar = VSFlex7.OutlineBarSettings.flexOutlineBarSimple;
kly> DocumentGrid.Cols = 11;
kly> DocumentGrid.Rows = 40;
kly> //....
kly>}
kly>