ActiveX & VB6
От: maximum28  
Дата: 01.11.03 08:58
Оценка:
Появилась проблема. Во время исполнения программы нужно встроить объект ActiveX из OCX файла, путь к которому находит сама программа. Методы и свойства объекта программе известны.
Re: ActiveX & VB6
От: VinMike Россия  
Дата: 01.11.03 15:09
Оценка: -1
Здравствуйте, maximum28, Вы писали:

M>Появилась проблема. Во время исполнения программы нужно встроить объект ActiveX из OCX файла, путь к которому находит сама программа. Методы и свойства объекта программе известны.

Если мне память не изменяет то поможет :
dim OCX as Object
set OCX=GetObject("C:\MyCool.ocx")
Удачи
Re[2]: ActiveX & VB6
От: maximum28  
Дата: 03.11.03 07:31
Оценка:
Здравствуйте, VinMike, Вы писали:

VM>Здравствуйте, maximum28, Вы писали:


M>>Появилась проблема. Во время исполнения программы нужно встроить объект ActiveX из OCX файла, путь к которому находит сама программа. Методы и свойства объекта программе известны.

VM>Если мне память не изменяет то поможет :
VM>dim OCX as Object
VM>set OCX=GetObject("C:\MyCool.ocx")
VM>Удачи

Спасибо за совет, VinMike.
Синтаксис GetObject ([PathName], [Class])
В Вашем примере указывается только путь. Если ввести даже правильный путь (например, "C:\WINNT\System32\mci32.ocx"), то появляется сообщение об ошибке:
Run-time error '432'
File name or class name not found during Automation operation
Вопрос: Как определить Class name по имени файла?
Re[3]: ActiveX & VB6
От: LantY Россия icq:56949749
Дата: 03.11.03 11:56
Оценка:
Здравствуйте, maximum28, Вы писали:
M>Спасибо за совет, VinMike.
M>Синтаксис GetObject ([PathName], [Class])
M>В Вашем примере указывается только путь. Если ввести даже правильный путь (например, "C:\WINNT\System32\mci32.ocx"), то появляется сообщение об ошибке:
M>Run-time error '432'
M>File name or class name not found during Automation operation
M>Вопрос: Как определить Class name по имени файла?

Тогда уж дочитывай описание функции до конца. (А заодно и описание ошибки)

Dim CADObject As Object
Set CADObject = GetObject("C:\CAD\SCHEMA.CAD")

When this code is executed, the application associated with the specified pathname is started and the object in the specified file is activated.

....

Note Use the GetObject function when there is a current instance of the object or if you want to create the object with a file already loaded. If there is no current instance, and you don't want the object started with a file loaded, use the CreateObject function.

Кратко: функция загружает экземпляр объекта из файла (например рисунок), при этом для загрузки используются существующие в системе соответствия файлов.
И потом, я, например, не могу представить ситуацию в которой требуется ПРОГРАММНО подгрузить ocx-файл, не зная при этом о нем ничего. Какой в этом смысл?
С уважением, Дмитрий.
Re[4]: ActiveX & VB6
От: VinMike Россия  
Дата: 03.11.03 12:29
Оценка:
Здравствуйте, LantY, Вы писали:
LY>И потом, я, например, не могу представить ситуацию в которой требуется ПРОГРАММНО подгрузить ocx-файл, не зная при этом о нем ничего. Какой в этом смысл?
Очень просто:
-если требуется обновлять или изменять местоположение Ax или COM Dll перед использованием.
Re[4]: ActiveX & VB6
От: maximum28  
Дата: 04.11.03 05:27
Оценка:
Здравствуйте, LantY, Вы писали:

LY>И потом, я, например, не могу представить ситуацию в которой требуется ПРОГРАММНО подгрузить ocx-файл, не зная при этом о нем ничего. Какой в этом смысл?


Спасибо за ответ.
Ситуация следующая: нужно создать поддержку Plug-in'ов на основе ActiveX компонент.
Re[2]: ActiveX & VB6
От: Vi2 Удмуртия http://www.adem.ru
Дата: 04.11.03 06:07
Оценка: 2 (1)
Здравствуйте, VinMike, Вы писали:

VM>Если мне память не изменяет то поможет :
VM>dim OCX as Object
VM>set OCX=GetObject("C:\MyCool.ocx")

Этот путь неправильный. И из-за причины двоякого рода.

Во-первых, формат функции GetObject GetObject(файл_с_данными,...). С данными, а не с кодами.

Во-вторых, OCX файлы содержат ActiveX Control-ы, которые не работают без контейнера. Поэтому если в принципе и можно создать экземпляр компонента (например, через GetObject или CreateObject), то он все равно будет не рабочим. ActiveX Control-ы загружаются не таким образом.

Вот один из способов
Form.Controls.Add ProgID, name, container

Добавляет контрол к коллекции Controls формы и возвращает ссылку на созданный контрол.

ProgID — это строка с ProgID компонента. Например, в вышеприведенном примере, "MyCool.Component" или "VB.CommandButton"
name — это имя будущего объекта
container — это будущий контейнер объекта, если он должен быть расположен не на форме.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[5]: ActiveX & VB6
От: LantY Россия icq:56949749
Дата: 04.11.03 06:26
Оценка:
Здравствуйте, maximum28, Вы писали:

M>Здравствуйте, LantY, Вы писали:


LY>>И потом, я, например, не могу представить ситуацию в которой требуется ПРОГРАММНО подгрузить ocx-файл, не зная при этом о нем ничего. Какой в этом смысл?


M>Спасибо за ответ.

M>Ситуация следующая: нужно создать поддержку Plug-in'ов на основе ActiveX компонент.
OCX компоненты нужно регистрировать и(!) размещать на форме. Иначе они не будут работать.

В общем тебе прямиком к dll-кам и функции LoadLibrary.
Вот только непосредственно под VB ее нет, а как будет работать импортированная из виндов — не знаю, не проверял
IMHO тогда проще писать на Си или Дельфи.
С уважением, Дмитрий.
Re[3]: ActiveX & VB6
От: maximum28  
Дата: 04.11.03 08:25
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Вот один из способов

Vi2>Form.Controls.Add ProgID, name, container

Vi2>Добавляет контрол к коллекции Controls формы и возвращает ссылку на созданный контрол.


Vi2>ProgID — это строка с ProgID компонента. Например, в вышеприведенном примере, "MyCool.Component" или "VB.CommandButton"

Vi2>name — это имя будущего объекта
Vi2>container — это будущий контейнер объекта, если он должен быть расположен не на форме.

Не могли бы Вы подсказать, а как определить ProgID компонента по пути к его файлу.
С уважение Максим
Re[4]: ActiveX & VB6
От: Vi2 Удмуртия http://www.adem.ru
Дата: 04.11.03 09:28
Оценка: 3 (1)
Здравствуйте, maximum28, Вы писали:

M>Не могли бы Вы подсказать, а как определить ProgID компонента по пути к его файлу.

Честно сказать, это не благодарная задача. Потому что нет никакой логической связи между OCX файлом (ни по названию, ни по внутренностям) и ProgID компонента, хотя бы просто потому что в этом файле может быть несколько компонент. Но даже если там находится один компонент, единственное место, которое устанавливает эту связь, — это Реестр. Итак, СОМ программы идут таким путем: HKCR\<ProgID>\CLSID => CLSID компонента, HKCR\CLSID\<CLSID>\InProcServer32 => полный путь к файлу компонента. Поэтому нужно просмотреть Реестр для всех HKCR\CLSID\<CLSID> и найти все такие <CLSID>, для которого установлен твой файл. Дальше, второй проход, просмотреть Реестр для всех HKCR\<ProgID> и найти такие <ProgID>, для которых установлены найденные CLSID.

API функций, полностью упрощающих эту задачу, нет. Хотя есть функция ProgIDFromCLSID и объект TypeLib Information, который может вытащить CLSID из файла OCX, потому что содержит внутри TLB. Примерно, по такому сценарию

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, _
                                                             ByVal Source As Long, ByVal Length As Long)
Private Declare Function CLSIDFromString Lib "ole32" (ByVal OleStringCLSID As Long, myGUID As Any) As Long
Private Declare Function ProgIDFromCLSID Lib "ole32" (myGUID As Any, lplpszProgID As Long) As Long
Private Declare Function CoTaskMemFree Lib "ole32" (ByVal lplpszProgID As Long) As Long

Private Sub Form_Load()
  Dim ta As TLI.TLIApplication, tl As TLI.TypeLibInfo, tc As TLI.CoClassInfo
  Dim sCLSID As String
  
  Set ta = New TLI.TLIApplication
  Set tl = ta.TypeLibInfoFromFile("твой файл.ocx")
  For Each tc In tl.CoClasses
    sCLSID = GetProgID(tc.Guid)
  Next
End Sub

Public Function GetProgID(ByVal sCLSID As String) As String
  Dim myGUID(0 To 15) As Byte, iProgID As Long, sProgID(0 To 255) As Byte
  
  On Error Resume Next
  
  CLSIDFromString StrPtr(sCLSID), myGUID(0)
  ProgIDFromCLSID myGUID(0), iProgID
  CopyMemory sProgID(0), iProgID, 256
  sCLSID = sProgID
  sCLSID = Left(sCLSID, InStr(sCLSID, vbNullChar) - 1)
  CoTaskMemFree iProgID
  GetProgID = sCLSID
End Function

Смотри сам, что проще.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[5]: ActiveX & VB6
От: GarryIV  
Дата: 04.11.03 10:45
Оценка: 3 (1)
Здравствуйте, maximum28! Вы писали:

LY>> И потом, я, например, не могу представить ситуацию в которой требуется

LY>> ПРОГРАММНО подгрузить ocx-файл, не зная при этом о нем ничего. Какой в
LY>> этом смысл?

m> Спасибо за ответ.

m> Ситуация следующая: нужно создать поддержку Plug-in'ов на основе ActiveX
m> компонент.

Вобщем делать надо так

1. Сделать интерфейс IMyPlugin (как на VB это делать не знаю)
2. Все плагины должны реализовать этот интерфейс (Implement IMyPlugin)
3. После этого добавить в основную прогу ссылку на ActiveX реализующий интерфейс (например записать в реестр или ini или куда)
4. В основной проге делаем CreateObject() и далее дергаем наш плагин через интерфейс IMyPlugin.

Точно так работают плагины для MS Office (только они Add-in'ами зовутся) там интерфейс зовется IDTExtensibility2
Posted via RSDN NNTP Server 1.8 beta
WBR, Igor Evgrafov
Re[5]: ActiveX & VB6
От: maximum28  
Дата: 06.11.03 05:26
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>
Vi2>Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, _
Vi2>                                                             ByVal Source As Long, ByVal Length As Long)
Vi2>Private Declare Function CLSIDFromString Lib "ole32" (ByVal OleStringCLSID As Long, myGUID As Any) As Long
Vi2>Private Declare Function ProgIDFromCLSID Lib "ole32" (myGUID As Any, lplpszProgID As Long) As Long
Vi2>Private Declare Function CoTaskMemFree Lib "ole32" (ByVal lplpszProgID As Long) As Long

Vi2>Private Sub Form_Load()
Vi2>  Dim ta As TLI.TLIApplication, tl As TLI.TypeLibInfo, tc As TLI.CoClassInfo
Vi2>  Dim sCLSID As String
  
Vi2>  Set ta = New TLI.TLIApplication
Vi2>  Set tl = ta.TypeLibInfoFromFile("твой файл.ocx")
Vi2>  For Each tc In tl.CoClasses
Vi2>    sCLSID = GetProgID(tc.Guid)
Vi2>  Next
Vi2>End Sub

Vi2>Public Function GetProgID(ByVal sCLSID As String) As String
Vi2>  Dim myGUID(0 To 15) As Byte, iProgID As Long, sProgID(0 To 255) As Byte
  
Vi2>  On Error Resume Next
  
Vi2>  CLSIDFromString StrPtr(sCLSID), myGUID(0)
Vi2>  ProgIDFromCLSID myGUID(0), iProgID
Vi2>  CopyMemory sProgID(0), iProgID, 256
Vi2>  sCLSID = sProgID
Vi2>  sCLSID = Left(sCLSID, InStr(sCLSID, vbNullChar) - 1)
Vi2>  CoTaskMemFree iProgID
Vi2>  GetProgID = sCLSID
Vi2>End Function
Vi2>

Vi2>Смотри сам, что проще.

Спасибо, Vi2, за полезный совет, но … он не работает
Это я о втором.
Если в Вашем примере убрать строку
On Error Resume Next,
то в строке
CLSIDFromString StrPtr(sCLSID), myGUID(0)
возникает ошибка:
Run-time error ‘49’
Bad DLL calling convention.
В общем, программа загибается на OLE32-функциях.
Если не сложно, не могли бы вы подсказать, где найти документацию по этим функциям (MSDN не помогло (версия под .NET)). И последняя просьба: у Вас есть файл с объявлениями OLE32-функций для VB6 для API Viewer’а? Если да, то, если не сложно, скиньте мне его на e-mail: maximum28@yandex.ru
С уважением, Максим.
Re[6]: ActiveX & VB6
От: Vi2 Удмуртия http://www.adem.ru
Дата: 06.11.03 08:23
Оценка:
Здравствуйте, maximum28, Вы писали:

M>... в строке CLSIDFromString StrPtr(sCLSID), myGUID(0) возникает ошибка:
M>Run-time error ‘49’
M>Bad DLL calling convention.
M>В общем, программа загибается на OLE32-функциях.

Этого не может быть, потому что не может быть никогда. CLSIDFromString просто обязана работать. У меня были сомнения в ProgIDFromCLSID, но вроде бы я преодолел трудности. Хотя, видимо, это зависит от версии используемой Win. А отсюда мораль: не использовать WinAPI ни под каким соусом. Лично я так и делаю. Если нужен доступ к ним, то, продумав, реализую через COM объект.

Что посоветовать? Претворять в жизнь просмотр Реестра.

M>Если не сложно, не могли бы вы подсказать, где найти документацию по этим функциям (MSDN не помогло (версия под .NET)). И последняя просьба: у Вас есть файл с объявлениями OLE32-функций для VB6 для API Viewer’а?

Нет, у меня такого файла нет.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[7]: ActiveX & VB6
От: maximum28  
Дата: 10.11.03 06:40
Оценка:
Здравствуйте, Vi2,
А всё-таки она крутиться... Ваш вариант с API функциями работает, хоть и не всегда. Но для моих целей достаточно. БОЛЬШОЕ спасибо. Но возникла еще одна проблема. Нельзя обратиться к нестандартным свойствам и методам ActiveX компонента. Только к свойствам Extender'а. Со стандартными элементами, типа VB.TextBox работает, если объявить создаваемый объект как TextBox, А как быть в моём случае? Все подключаемые ActiveX компоненты имеют заранее оговоренные методы и свойста.
Re[8]: ActiveX & VB6
От: Vi2 Удмуртия http://www.adem.ru
Дата: 11.11.03 04:36
Оценка:
Здравствуйте, maximum28, Вы писали:

M>Нельзя обратиться к нестандартным свойствам и методам ActiveX компонента. Только к свойствам Extender'а. Со стандартными элементами, типа VB.TextBox работает, если объявить создаваемый объект как TextBox, А как быть в моём случае? Все подключаемые ActiveX компоненты имеют заранее оговоренные методы и свойста.

Трудно судить что ты там делаешь. Но от Extender всегда можно перейти к объекту, т.к. он имеет свойство Object, возвращающее твой объект. И, как любой Object VB-а, он может работать с поздним связыванием.

Оговоренные методы и свойста могут иметь одинаковые имена, но принадлежать разным классам (сиречь, СОМ интерфейсам). Здесь можно работать только с поздним связыванием (без подсказок со стороны VB).

Оговоренные методы и свойста могут быть объявлены в некотором классе, который имплементируется во всех твоих ActiveX компонентах через Implements этот_некоторый_класс. Тогда можно было бы работать и с ранним связыванием через приведение объекта к этому классу.

Dim comp As этот_некоторый_класс
Set comp = ctl
Set comp = ctl.Extender
Set comp = ctl.Extender.Object
пока comp не станет содержать нечто.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[9]: ActiveX & VB6
От: maximum28  
Дата: 11.11.03 10:34
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Здравствуйте, maximum28, Вы писали:


Vi2>Оговоренные методы и свойста могут иметь одинаковые имена, но принадлежать разным классам (сиречь, СОМ интерфейсам). Здесь можно работать только с поздним связыванием (без подсказок со стороны VB).


В том-то и проблема, что позднее связывание не работает.
Втраиваю ActiveX компонент в программу на лету через form.Controls.Add(ProgID,...), заранее определив ProgID с использованием того метода, который Вы, ещё раз спасибо, мне подсказали. Если теперь в коде указать:

Set NewPlugIn = form.Controls.Add(ProgID, "xxx")
NewPlugIn.Visible=True


Пока работает.
Теперь пробуем обратиться к специальному,заранее оговоренному, свойству, например, AdditionalSettings.

Temp = NewPlugIn.AdditionalSettings

А вот здесь появляется сообщение:
Объект не поддерживает данное свойство или метод.

Хотя, если встраивать объект на стадии конструирования, то эта же строка кода работает...
Re[10]: А так?
От: Vi2 Удмуртия http://www.adem.ru
Дата: 11.11.03 11:32
Оценка:
Здравствуйте, maximum28, Вы писали:

M>Теперь пробуем обратиться к специальному,заранее оговоренному, свойству, например, AdditionalSettings.

M>Temp = NewPlugIn.AdditionalSettings

M>А вот здесь появляется сообщение: Объект не поддерживает данное свойство или метод.
M>Хотя, если встраивать объект на стадии конструирования, то эта же строка кода работает...

А так?
Temp = NewPlugIn . Object . AdditionalSettings
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[11]: А так РАБОТАЕТ!!!
От: maximum28  
Дата: 15.11.03 10:27
Оценка:
БОЛЬШОЕ спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.