Проблемы с передачей в UserControl в качестве параметра в VB6 - PullRequest
2 голосов
/ 14 мая 2009

У меня есть COM-видимый метод, который выглядит примерно так:

Public Sub SomeMethod(someControl as Object)
On Error Goto ErrHandler    

Dim someSpecificControl as SpecificControl

   MsgBox TypeOf someControl is Control
   MsgBox TypeOf someControl is SpecificControl

   On Error Resume Next
   Set someSpecificControl = someControl
   On Error Goto ErrHandler
   if someSpecificControl is Nothing then
      Exit Sub
   end if

   ' do stuff to the control

End Sub

Другие компоненты будут вызывать этот метод (то есть через COM) и передавать элемент управления типа SpecificControl.

Моя проблема заключается в том, что при запуске через отладчик параметризованный элемент управления не соответствует нужному типу, т. Е. Выходит из подпрограммы после сбоя «cast», когда я ожидал, что этого не произойдет.

Использование TypeOf Я проверил, что параметризованный объект имеет тип Control (как выше), но я не могу понять, почему он был передан - по-видимому - неправильно. Кажется, он работает правильно, когда работает вне отладчика - но я не уверен (отсюда этот вопрос).

Может кто-нибудь пролить свет на это? Может ли элемент управления каким-то образом быть поврежден в процессе распаковки? Есть ли лучший способ сделать это?

Редактировать: я использовал TypeName, как подсказал Крис Эриксон, и получил несколько интересных результатов:

MsgBox TypeName(someControl) 
MsgBox "someControl is of type SpecificControl: " & TypeOf someControl is SpecificControl
MsgBox "someControl is of type UserControl: " & TypeOf someControl is UserControl
MsgBox "someControl is of type Control: " & TypeOf someControl is Control

Я получаю:

SpecificControl
someControl is of type SpecificControl: False
someControl is of type UserControl: False
someControl is of type Control: True

Полагаю, единственный способ избежать этого - избегать передачи UserControl в качестве параметра.

Ответы [ 2 ]

3 голосов
/ 18 мая 2009

Я использую VBControlExtender в качестве типа параметра

Public Sub SomeMethod(someControl as VBControlExtender)

тогда я получаю такие ссылки

Dim someSpecificControl as SpecificControl
Dim someSpecificControlExt as VBControlExtender

Set someSpecificControl = someControl.object
Set someSpecificControlExt = someControl

Затем используйте someSpecificControlExt для доступа к Left, TabIndex, TabStop, Name, Move и т. Д. Свойств расширителя и someSpecificControl для доступа к определенным методам / свойствам моего пользовательского элемента управления. .

К вашему сведению, поведение вашего кода зависит от того, реализован ли пользовательский элемент управления в текущем проекте или на который имеется ссылка в ocx. Я использую Мэтт Керлендс также взломать доступ для прямого контроля пользователя , что позволяет мне сделать это

Dim someSpecificControl as DirectSpecificControl

, так что someSpecificControl реквизиты / методы доступны с ранним ограничением.

Вот как я получаю someSpecificControlExt (расширитель) от элемента управления:

Public Function GetExtendedControl(oCtl As IUnknown) As VBControlExtender
    Dim pOleObject      As IOleObject
    Dim pOleControlSite As IOleControlSite

    On Error Resume Next
    Set pOleObject = oCtl
    Set pOleControlSite = pOleObject.GetClientSite
    Set GetExtendedControl = pOleControlSite.GetExtendedControl
    On Error GoTo 0
End Function

Вот как я получаю внутренний UserControl пользовательского элемента управления VB6:

Public Function GetUserControl(oObj As Object) As UserControl
    Dim pControl        As UserControl

    Call CopyMemory(pControl, ObjPtr(oObj), 4)
    Set GetUserControl = pControl
    Call CopyMemory(pControl, 0&, 4)
End Function

Ссылка GetUserControl Return имеет очень странную реализацию QueryInterface - похоже, интерфейс UserControl специально указан в E_NOTIMPLEMENTED.

1 голос
/ 14 мая 2009

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

Так что, если вы

Private Sub AdjustControlProperties(oControl as MyUserControl)
...
End Sub

Как только элемент управления покидает вашу подпрограмму, он будет работать как элемент управления, а не как пользовательский элемент управления (у вас больше не будет доступа к свойствам элемента управления пользовательским, и попытки доступа к ним приведут к ошибке). Очень странная ошибка в VB6, и одна из них вызвала много потянув за волосы.

Private Sub AdjustControlProperties(oControl as Object)
...
End Sub

И все хорошо. Я предполагаю, что вы правы, а UserControls упакованы, распакованы, так как Control не UserControls. Единственное решение для проверки типов, это использовать

TypeName()

чтобы знать, какой это тип, поскольку он не будет поврежден.

...