Вопрос по Пользовательскому типу данных (VB6)

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
CyberPunk
Начинающий
Начинающий
 
Сообщения: 12
Зарегистрирован: 23.06.2006 (Пт) 7:54

Вопрос по Пользовательскому типу данных (VB6)

Сообщение CyberPunk » 18.04.2012 (Ср) 10:35

Есть некоторые пользовательские типы данных.

Например

' 2D Point
Public Type Point2d
x As Single
y As Single
End Type

' 3D Point
Public Type Point3d
x As Single
y As Single
Z As Single
End Type

Вопрос в следующем.

Можно ли, и если можно, то как, создать функцию, которая на входе может получать любой из этих типов (Variant ?) и в зависимости от типа данных на входе, выполняющую разные действия.

Т.е. по сути тут два вопроса.

1.Как передать эти типы в одну переменную.
2. Как определить, какого типа переменная пришла на вход функции.

Заранее спасибо.

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение jangle » 18.04.2012 (Ср) 10:40

Можно передавать указатель на эту структуру, а тип структуры определять по дополнительному полю t в котором хранится айдишник типа, например 1- для Point2d, 2 - для Point3d

Public Type Point2d
t as Byte
x As Single
y As Single
End Type

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 18.04.2012 (Ср) 23:05

Не помню, было ли это в VB6:
Код: Выделить всё
Dim X as Variant
...
If TypeOf X Is Point2d Then ...

Вариант из области извращений: обратиться к полю Z - в случае ошибки Point2d.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение arthur2 » 19.04.2012 (Чт) 19:51

Qwertiy писал(а):Вариант из области извращений
Именно. Вариант не может содержать пользовательского типа.
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16475
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение Хакер » 19.04.2012 (Чт) 20:26

Может, не надо распространять лжеинформацию.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение arthur2 » 19.04.2012 (Чт) 20:31

А что, может?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16475
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение Хакер » 19.04.2012 (Чт) 21:17

В моём предыдущем после слово «Может» было вовсе не вводным.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение arthur2 » 19.04.2012 (Чт) 21:42

arthur2 писал(а):Вариант не может содержать пользовательского типа.
Хакер писал(а):Может, не надо распространять лжеинформацию.
Итак, может ли вариант содержать пользовательский тип?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16475
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение Хакер » 19.04.2012 (Чт) 21:44

arthur2 писал(а):
Хакер писал(а):Может, не надо распространять лжеинформацию.
Итак, может ли вариант содержать пользовательский тип?

Хакер писал(а):Может, не надо распространять лжеинформацию.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение arthur2 » 19.04.2012 (Чт) 21:50

Слушай, ну ответь хоть раз без выкрутасов - в чем ложная информация-то?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16475
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение Хакер » 19.04.2012 (Чт) 22:01

Ложная информация в том, что Variant не может содержать внутри себя рекорд.
Истинная информация в том, что Variant может содержать внутри себя рекорд.

Неужели это так сложно?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение arthur2 » 19.04.2012 (Чт) 22:03

Так-с... перечитал. Внятнее было бы после "может" поставить точку.

Итак, как поместить в вариант пользовательский тип?

Код: Выделить всё
Option Explicit

Private Type a
b As Integer
c As Integer
           
End Type

Public Sub test()
Dim a As a, b
b = a

End Sub
---------------------------
Microsoft Visual Basic
---------------------------
Compile Error:

Only user-defined types defined in public object modules can be coerced to or from a variant or passed to late-bound functions
---------------------------
ОК Справка
---------------------------
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16475
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение Хакер » 19.04.2012 (Чт) 22:27

arthur2 писал(а):Итак, как поместить в вариант пользовательский тип?

В приведённой тобой цитате ошибки уже содержится ответ на этот вопрос.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение arthur2 » 20.04.2012 (Пт) 5:32

И всё-таки. У меня с инглишем плохо. По тексту ошибки, я так и не понял.
Артур
 
   

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение ger_kar » 20.04.2012 (Пт) 7:04

Хакер писал(а):В приведённой тобой цитате ошибки уже содержится ответ на этот вопрос.

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

Из чего можно сделать вывод, что для того чтобы передать UDT в вариант, объявить его в модуле класса, потому что под "общественными объектными модулями" я понял именно модуль класса, другого на ум ничего не пришло. Тогда по сути вариант будет содержать просто объектную ссылку. Из чего следует, что поместить в вариант напрямую пользовательский тип нельзя, но возможен обходной путь, через модуль класса. А в класс вообще много чего по сути обернуть можно. Вот такая мысля.
Бороться и искать, найти и перепрятать

Diamock
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 388
Зарегистрирован: 26.10.2009 (Пн) 4:19
Откуда: Кемерово

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение Diamock » 20.04.2012 (Пт) 7:28

CyberPunk писал(а):Вопрос в следующем.

Можно ли, и если можно, то как, создать функцию, которая на входе может получать любой из этих типов (Variant ?) и в зависимости от типа данных на входе, выполняющую разные действия.

Т.е. по сути тут два вопроса.

1.Как передать эти типы в одну переменную.
2. Как определить, какого типа переменная пришла на вход функции.

Заранее спасибо.

Передать пользовательские типы Point2d и Point3d можно с помощью составного типа, например

Код: Выделить всё
Public Type Point_d
    fPoint As Point2d
    sPoint As Point3d
End Type

И подробно опиши, какие действия будут производиться с Point2d и Point3d, от этого зависит возвращаемое значение функции, возможно тип Variant и не придётся использовать.
In der Beschrankung zeigt sich erst der Meister
Графоманю...

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16475
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение Хакер » 20.04.2012 (Пт) 8:41

ger_kar писал(а):Из чего можно сделать вывод, что для того чтобы передать UDT в вариант, объявить его в модуле класса, потому что под "общественными объектными модулями" я понял именно модуль класса, другого на ум ничего не пришло.

Машинный перевод отправляется в задницу. Учебник по английскому языку отправляется тебе.



ger_kar писал(а):огда по сути вариант будет содержать просто объектную ссылку.

Логика — зашибись. Если объявить UDT внутри класса, то при присвоении этого UDT варианту в варианте с какого-то перепугу окажется объектная ссылка на класс? Да что это за бред?!

Ошибка гласит: только объявленные в public-модулях пользовательские типы могут быть приведены к/из типу Variant или переданы функциям, [вызываемым по механизму] позднего связывания.

Будет ли конкретно взятый object module (то есть класс, форма или контрол или ещё что-то в этом духе) являться public-чным зависит напрямую от выставленного свойства:
object_module_publicity.PNG
object_module_publicity.PNG (5.26 Кб) Просмотров: 10845


Всё предельно просто: если класс отмечен как Public, то он будет помещён в проектную TLB. И объявленный внутри него UDT тоже будет помещён в проектную TLB. А если класс Private — то в TLB ничего не будет помещено.

На самом деле, это VB-шные фокусы. С точки зрения голого типа COM, чтобы засунуть UDT в Variant, нужно чтобы кто-нибудь (не особо важно кто) реализовывал IRecordInfo для данного типа. Единственная причина того, что IRecordInfo существует — это для того, чтобы можно было засовывать UDT в Variant. А вы тут говорите — нельзя. Стыд!

В общем, для того, чтобы поместить UDT в Variant, изначально, нужно иметь ссылку на IRecordInfo для данного UDT, чтобы COM через этот интерфейс могла опросить кого-нибудь на предмет того, как правильно обращаться с UDT-шкой (чтобы хотя бы знать, какого она размера). Кто придумал UDT, кто реализует IRecordInfo — абсолютно не важно. Можно динамически на ходу во время выполнения придумывать случайные UDT-шки, и имея универсальную реализацию IRecordInfo, засовывать самые невероятные UDT-шки в Variant. Вручную.

В VB при работе с вариантом родными средствами языка предполагается, что UDT где-то объявлена. А вариантов «где-то» всего два: UDT объявлена в нашем проекте (в ассоциированной с нашим проектом TLB), либо UDT объявлена не в нашем проекте (значит в какой-то чужой неизвестно-какой TLB). И, соответственно, это описание из TLB используется при необходимости запихивания UDT в Variant. И значит, в конце-концов, чтобы запихать UDT в TLB родными средствами языка, нужно иметь описание UDT в любой TLB. Либо в проектной TLB, либо в сторонней TLB — абсолютно неважной.

А значит два варианта: либо вы нужный вам UDT объявляете в отдельном .tlb-файле (который сами создаёте любым мыслимым и приемлемым для вас способом, напимер, написал на IDL-е и скомпилировав MIDL-ом), либо вы объявлете UDT непосредственно VB-кодом, и описание этого UDT попадает в ассоциированную с текущим проектом TLB.

Для того, чтобы последнее осуществилось, то есть чтобы UDT попал в проектную TLB, надо чтобы класс, в котором объявлен UDT, был пабликом. А чтобы класс можно было сделать пабликом, тип проекта должен быть отличным от «Standard EXE». Ну а если у вас Standard EXE, то никто не отменяет возможность засунуть UDT в вариант — просто объявление UDT должно быть в какой-то другой TLB.

______

Мне категорически не хочется опять писать «кем надо быть», но ситуация вынуждает. Я не понимаю, как можно иметь такую извращённую логику, чтобы делать умозаключения, что поместить UDT в Variant нельзя.

Если бы UDT в Variant поместить было вообще нельзя (никогда), то разве не очевидно, что ошибка бы звучала просто «User-defined type can not be coerced to Variant». Но ошибка звучит не так. В ошибке гораздо больше слов, то есть даже если не читать текст ошибки, то и без этого понятно, что специфика момента гораздо сложнее, чем тупое «нельзя и усё тут».

Так вот: кем надо быть, чтобы, читая ошибку, в которой говорится «далеко не любой UDT может быть приведен к Variant-у», утверждать, что UDT вообще никогда в принципе не могут быть засунуты в Variant?

Объясните мне вашу логику, пожалуйста — это единственная непостижимая для меня вещь.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение ger_kar » 20.04.2012 (Пт) 9:06

Хакер писал(а):Логика — зашибись. Если объявить UDT внутри класса, то при присвоении этого UDT варианту в варианте с какого-то перепугу окажется объектная ссылка на класс? Да что это за бред?!
Почему бред? Если обернуть UDT в класс, то к UDT можно обратиться соответственно через экземпляр этого класса, ссылку на этот класс можно присвоить вариантной переменной объявленной как Object. Перечитал еще раз свой ответ, там все логично, потому что речь идет об оборачивании UDT в класс, соответственно в переменную типа объест (по сути вариантную) можно поместить ссылку на экземпляр этого класса. Если рассмотреть это глубже, то конкретно в ней будет содержаться ссылка на интерфейс IDispath. Если все сделать через класс, то все вполне будет работать.
Бороться и искать, найти и перепрятать

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение ger_kar » 20.04.2012 (Пт) 10:50

Хакер писал(а):Объясните мне вашу логику, пожалуйста — это единственная непостижимая для меня вещь.
Твое мышление (позволю себе высказаться за всех) тоже порой непостижимо. Я имею ввиду сам процесс мышления, а не готовые высказывания, которые являются его результатом. Т.е. когда читаешь понятно, но например мой мозг такое бы сам не сгенерировал. Хотя теперь уже да! Вобщем логика на то она и логика, что у всех она может быть разной, но вполне логичной. Отсюда масса анекдотов про логику. Потому что порой иная логика, что сам анекдот.
Бороться и искать, найти и перепрятать

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение jangle » 20.04.2012 (Пт) 10:55

Приведите пример кода как поместить UDT в Variant

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16475
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение Хакер » 20.04.2012 (Пт) 11:55

Код: Выделить всё
Dim v as variant
Dim r as SOME_RECORD

v = r
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение jangle » 20.04.2012 (Пт) 12:03

Only user-defined types defined in public object modules can be coerced to or from a variant or passed to late-bound functions

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16475
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение Хакер » 20.04.2012 (Пт) 12:09

Странно, а должно быть «User-defined type not defined». Это говорит только о том, что ты имел храбрость объявить тип SOME_RECORD, но объявил его неправильно. Сам-себе-злобный-буратино.

jangle, nы троллишь, или ты действительно испытываешь проблемы с пониманием и не понимаешь всего того, что написано выше, а именно того, где и как надо объявить UDT, чтобы ошибки, которую ты привёл, не было?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение jangle » 20.04.2012 (Пт) 13:14

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

Кстати в PB, присвоение UDT варианту делается почему-то элементарно.

Код: Выделить всё
#Compile Exe
#Dim All

Type SOME_RECORD
    x As Long
    z As Long
End Type


Function PBMain () As Long
Dim v As Variant
Dim r As SOME_RECORD

r.x=1
r.z=2

Let v = r As String

Dim r2 As SOME_RECORD

Let r2 = Variant$(Byte, v)

MsgBox Str$(r2.x)
MsgBox Str$(r2.z)
End Function
                       

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение ger_kar » 20.04.2012 (Пт) 13:51

Хакер писал(а):либо UDT объявлена не в нашем проекте (значит в какой-то чужой неизвестно-какой TLB). И, соответственно, это описание из TLB используется при необходимости запихивания UDT в Variant.
Тут все понятно. Идем дальше
Хакер писал(а):С точки зрения голого типа COM, чтобы засунуть UDT в Variant, нужно чтобы кто-нибудь (не особо важно кто) реализовывал IRecordInfo для данного типа. Единственная причина того, что IRecordInfo существует — это для того, чтобы можно было засовывать UDT в Variant.
Тут тоже все ясно, но почему
Хакер писал(а):Dim v as variant
Dim r as SOME_RECORD
v = r
Идет просто присвоение, где здесь использование IRecordInfo? Ладно с этим еще можно разобраться, если это не реализуется самим программером, то оно может быть реализовано компилятором непосредственно в коде и скрыто от программиста. Ну раз так все просто, почему бы и не провести эксперимент и закрепить вновь полученное знание на практике.
Что-бы не городить огород и все сделать по быстрому воспользуется вторым вариантом, когда UDT объявлена не в нашем проекте. Для этого я заюзал тип WIN32_FIND_DATA из подключенной TLB Win32-2001.tlb. Вот модуль кода, простой модуль.
Код: Выделить всё
Option Explicit

'Private v As Variant
'Private r As WIN32_FIND_DATA

Public v As Variant
Public r As WIN32_FIND_DATA

Sub main()
    Test
End Sub

Sub Test()
'    Dim v As Variant
'    Dim r As WIN32_FIND_DATA
    v = r
End Sub

Вобщем объявлял по разному как видно из кода, но в любом случае получается, как писал
jangle писал(а):Only user-defined types defined in public object modules can be coerced to or from a variant or passed to late-bound functions

Хакер писал(а):Это говорит только о том, что ты имел храбрость объявить тип SOME_RECORD, но объявил его неправильно. Сам-себе-злобный-буратино.jangle, nы троллишь, или ты действительно испытываешь проблемы с пониманием и не понимаешь всего того, что написано выше, а именно того, где и как надо объявить UDT, чтобы ошибки, которую ты привёл, не было?
Я тоже теперь уже не понимаю, ибо на практике получается облом. Как еще обявлять то? Выходит со вторым способом облом, остается только первый.
Бороться и искать, найти и перепрятать

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение ger_kar » 20.04.2012 (Пт) 14:10

Вобщем проверил первый вариант, он вполне сработал, так как и ожидалось, но вот второй вариант с чужой TLB фиг!

Может я внатуре что-то неправильно делал х.з. Но не РАБОТАЕТ!!!
Бороться и искать, найти и перепрятать

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение jangle » 20.04.2012 (Пт) 14:44

Нашел исходник для упаковки UDT в вариант и обратно. UDT должно быть в ActiveX Dll, отстой короче
Вложения
Enumerate_2029021142006.zip
(3.64 Кб) Скачиваний: 173

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение ger_kar » 20.04.2012 (Пт) 15:36

jangle писал(а):Нашел исходник для упаковки UDT в вариант и обратно. UDT должно быть в ActiveX Dll, отстой короче
Посмотрел код, собственно основная функция там UDT_Get_Info, которая просто извлекает информация из варианта, что касается упаковки UDT в вариант и обратно, то там это собственно и не реализовано, точнее оно реализовано именно через первый способ, который описал Хакер, там идет обычное присвоение v = udt. Поэтому нужна либо ActiveX.Dll, либо ActiveX.EXE. Кроме основной функции идут вспомогательные для реализации вызова ф-ций по указателю с любым количеством аргументов. Поэтому этот код, а точнее его идею, можно использовать совместно с волшебшными указателями Хакера и написать пару своих ф-ций для упаковки распаковки, что бы работали в обычном модуле и стандартном приложении. Там собственно большая часть кода относится к реализации вызова по указателю нежели к самой работе с интерфейсом IRecordInfo.
Бороться и искать, найти и перепрятать

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16475
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение Хакер » 21.04.2012 (Сб) 3:36

ger_kar писал(а):Идет просто присвоение, где здесь использование IRecordInfo?

В фоне, блин, в фоне! Вы издеваетесь или оба такие трудные?

ger_kar писал(а):Вобщем объявлял по разному как видно из кода, но в любом случае получается, как писал

Это ты заюзал кривую TLB. Любая сущность в TLB должна иметь UUID, потому что только UUID однозначно идентифицирует сущность, а строковое имя — это только удобная примочка для программиста (чтобы он не запутался, ведь UUID-ы в коде использовать неудобно). В твоей TLB при объявлении UDT-шек не были указаны UUID-ы. VB проявил себя достаточно хорошо: он всё равно позволил работать с таким кривым UDT, до тех пор, пока дело не выходило за границы VB, но как только дело дошло до глобальных коммуникаций, ну уж извините, с UDT без уникального идентификатора ничего не сделаешь.


jangle писал(а):Нашел исходник для упаковки UDT в вариант и обратно. UDT должно быть в ActiveX Dll, отстой короче

Ох как же ты любишь находить чужой фекальный код и копаться с ним. Желаю PSC чтобы на их серверы упал метеорит и уничтожил к чёрту все эти шизофреничные исходники, обладающие такой степенью извращённости, что впору давать антипримию.


__________________________

Ещё раз, для трудных.

Для того, чтобы поместить UDT в Variant-переменную, изначально, в соответствии с природой вещей, нужна реализация IRecordInfo.

Для того, что поместить UDT в Variant-переменную в рамках VB-кода обычным присвоением, нужно, чтобы существовала TLB, в которой описан UDT. Если UDT описан в TLB, то можно получить ITypeLib для TLB, далее получить ITypeInfo для UDT, и далее имея ITypeInfo получить IRecordInfo. Имея IRecordInfo для UDT можно присвоить UDT в Variant-переменную. Всю эту работу VB делает сам, мы всего лишь пишем:
v = r

Чтобы UDT был объявлен в TLB:
  • Либо он должен быть объявленным в TLB-шке текущего проекта. Но для этого нужно, чтобы наш проект имел тип «ActiveX EXE», либо «ActiveX DLL», либо «ActiveX Control». Потому что у проекта типа Standard EXE своей TLB нет.
  • Либо он должен быть объявлен в любом стороннем аналогичном проекте, а наш проект при этом может быть Standard EXE.
  • Либо он должен быть объявлен в отдельно лежащем TLB-файле. Не важно, как последний появился на свет.

Соответственно три варианта.

Первый вариант
Для тех, кто считает, что наш проект всенепременно должен иметь тип Standard EXE. Если вы по религиозным соображениям не можете поменять тип своего проекта со «Standard EXE» на «ActiveX EXE», то просто объявите UDT в отдельном проекте ActiveX-типа.

Вот образец.
2proj=std+actx.zip
(3.16 Кб) Скачиваний: 186
В архиве два проекта:
Первый проект MainProject типа Standard EXE, в котором и происходит вся работа с UDT и вариантами.
Второй проект TypeContainerPrj типа ActiveX DLL, нужный исключительно как контейнер для объявления UDT.
Читайте внимательно код. Как видите, можно работать с UDT, хранимым внутри Variant-а, даже не преобразовывая Variant к типу UDT!

Второй вариант
Те, кто пишет ActiveX-контрол, или ActiveX DLL, или ActiveX EXE, или кто может себе позволить преобразовать Standard EXE в ActiveX EXE:
1proj=actx.zip
(9.24 Кб) Скачиваний: 183
В архиве только один проект. По функционалу — точная копия MainProj из первого примера.

Третий вариант
Для тех, кто знает, что такое TLB, кто либо уже имеет TLB с нужными типами, либо может сам сделать такую. Кто понимает, что достаточно иметь TLB с описанием нужного типа, и вовсе необязательно для обладания ею привлекать в дело дополнительный ActiveX-проект или самому становиться ActiveX-проектом.
1proj=std+tlb.zip
(3.45 Кб) Скачиваний: 191
В архиве проект типа Standard EXE из самого первого примера и TLB-шка с описаниями типов.

Подчёркиваю: что эти три случая — те редкие случаи, когда проект, использующий TLB, становится зависимым от TLB, и TLB нужна после компиляции. В 99,99 % случаев TLB после компиляции не нужна (скомпилированный файл от неё не зависит и носить её с собой не нужно). Но в этом — нужна.
____________________

Итак, целых три варианта, демонстрирующих конвертацию UDT→Variant, обратную конвертацию Variant→UDT, и даже обращение к полям UDT без извлечения UDT из Variant переменной. И после этого вы посмеете сказать, что нельзя поместить UDT в Variant-переменную?

А ещё обращаю ваше внимание на то, что Variant-значение, содержащее внутри себя UDT, можно передать в VBScript! VBScript — это вообще язык без типов. В нём нет привычных типов Integer, Long, Double и т.п. Но благодаря СOM вы можете из VBScript-а работать с имеющими тип полями UDT-шки. VBScript может заполнить поля UDT-шки и передать её прямо в С++-компонент, и С++-компонент сможет работать с полями struct-а напрямую, то есть struct со стороны VBScript-а придёт именно в таком виде, в каком он (struct) объявлен.

А вы... нельзя-нельзя. Мне даже обидно за то, какую работу проделали неизвестные герои, чтобы всё это поддерживалось и работало, в то время как вы просто отрицаете существование всех этих возможностей.

_____________________

И ещё.
Есть несколько языков, которые позволяют следующее.

В JavaScript можно написать так:
Код: Выделить всё
foo = {'field_a' : 123, 'field_b' : 'hello!', 'field_c' : some_var};

А потом обращаться к foo.field_a, foo.field_b и foo.field_c. То есть создать как бы структуру, набор полей которой определяется в самый последний момент, динамически. То есть это будет объектом с заданным набором полей, набор задан в run-time, значения заданы сразу же при задании набора полей. Методов нет.

В PHP можно написать так:
Код: Выделить всё
$foo = array('aaa' => 123, 'bbb' => 'hello!', 'ccc' => $some_var);

Правда это будет массив, но всё равно есть некоторая видимость (всего-лишь видимость) того, что это как бы структура с заданным набором полей. К псевдополям можно будет обратиться как к $foo['aaa'], $foo['bbb'] и $foo['ccc'].

Так вот.
Это всё были скриптовые языки. Языки, в которых вообще нет типов. Языки с утиной типизацией.


А теперь поговорим о классических языках. О Си, Си++ или VB. О компилуемых языках. О языках, в которых более строгая типизация, в которых структуры нужно обязательно объявить, прежде чем использовать. О языках, в которых есть базовые скалярные типы: Integer, Long, Boolean и тому подобное.

Вы можете себе представить, говоря о таких языках, в частности, говоря о VB, функцию, которая принимает два аргумента:
  • Описание нового UDT (то есть его полей) на языке VB, как параметр типа String.
  • Массив значений для полей такого UDT

И возвращает такой UDT, у которого есть указанные поля, которые к тому же ещё и проинициализированны указанными значениями? То есть как в JS и PHP, но динамически задан не только набор полей, их имена и значения, но и типы этих полей (которых в JS и PHP просто быть не может).

Звучит как фантастика, но COM позволяет это сделать благодяря Variant-у.

Иными словами:
Код: Выделить всё
zoo = CreateNewUDT("Type ABSOLUTELY_NEW_UDT: a as long: b as integer: c as double: End Type", 44, 55, 66)
MsgBox TypeName(zoo) ' Даст ABSOLUTELY_NEW_UDT
Msgbox TypeName(zoo.a) ' Даст Long
MsgBox TypeName(zoo.b) ' Даст Integer
MsgBox TypeName(zoo.c) ' Даст Double

Код: Выделить всё
MsgBox zoo.a ' Даст 44
MsgBox zoo.b ' Даст 55
MsgBox zoo.c ' Даст 66
zoo.c = (zoo.a + zoo.b) / 2 ' поле «с» станет равно значению 49.5


Строчка с описанием структуры — динамическая, и берётся откуда угодно.
Набор начальных значений — аналогично.
А саму структуру можно передать, скажем, в API функцию, и API-функция увидит структуру в том виде, в каком должна, то есть как если бы это был по-обычному объявлённый UDT.

Вот какие трюки позволяет делать Variant! Не то что рядовое примитивное хранение обычных UDT внутри себя.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Вопрос по Пользовательскому типу данных (VB6)

Сообщение ger_kar » 21.04.2012 (Сб) 7:07

:shock: :shock: :shock:

Хакер писал(а):В фоне, блин, в фоне! Вы издеваетесь или оба такие трудные?
Мы не трудные, мы обыкновенные и откуда нам обыкновенным это было знать? Имеется ввиду информация по UDT и Variant. В Толстенной книженции по VB, которую я прочитал, а равно как и в других ничего подобного нет даже в помине. Ты телепат, мы нет! И та информацию которую я читал по COM, тоже ничего подобного не содержала. Что касается использования IRecordInfo в фоне, то тут худо-бедно, но на меня снизошло озарение, ибо я писал следующее: "Ладно с этим еще можно разобраться, если это не реализуется самим программером, то оно может быть реализовано компилятором непосредственно в коде и скрыто от программиста." Вот собственно, как раз про фон.

Хакер писал(а):Это ты заюзал кривую TLB.
Тут уж извините, не догадался, ибо ТЛБ шка в остальных случаях вполне себе хорошо работает.
Хакер писал(а):Ох как же ты любишь находить чужой фекальный код и копаться с ним. Желаю PSC чтобы на их серверы упал метеорит и уничтожил к чёрту все эти шизофреничные исходники, обладающие такой степенью извращённости, что впору давать антипримию.
Коды всякие нужны! Коды всякие важны!

Хакер писал(а):Ещё раз, для трудных.
А еще и для просто обыкновенных и даже для тех кто на бронепоезде :)
Хакер писал(а):Подчёркиваю: что эти три случая — те редкие случаи, когда проект, использующий TLB, становится зависимым от TLB, и TLB нужна после компиляции
А вот это Совсем нехорошо. Просто очень нехорошо. Но очень хорошо, что ты об этом предупредил. Мы не телепаты, сами бы фиг догадались! Исходя из написанного, лучше сделать свою обработку UDT<->Variant используя IRecordInfo, если уж сильно понадобится. Ну или как вариант заюзать ActiveX.exe, это все лучше чем таскание с библиотекой.
Бороться и искать, найти и перепрятать

След.

Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

    TopList