2009-05-14 2 views
2

Ich habe eine COM-sichtbare Methode, die in etwa wie folgt aussieht: diese Methode in einer Steuerung (dh über COM) und passieren würden rufenProbleme in einem Usercontrol als Parameter in VB6 vorbei

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 

Andere Komponenten vom Typ SpecificControl.

Mein Problem ist, dass, wenn über den Debugger ausgeführt wird, das parametrisierte Steuerelement nicht vom richtigen Typ zu sein, d. H. Es beendet die Subroutine, nachdem das "cast" fehlschlägt, wenn ich es nicht erwartet hätte.

Mit TypeOf habe ich überprüft, dass das parametrisierte Objekt vom Typ Control ist (wie oben), aber ich kann nicht herausfinden, warum es - scheinbar - falsch übergeben wurde. Es scheint sich korrekt zu verhalten, wenn es außerhalb des Debuggers ausgeführt wird - aber ich kann nicht sicher sein (daher diese Frage).

Kann jemand Licht darauf werfen? Könnte die Kontrolle - irgendwie - im Boxing-Unboxing-Prozess beschädigt worden sein? Gibt es einen besseren Weg, dies zu tun?

Edit: Ich habe TypeName wie durch Kris Erickson und bekam einige interessante Ergebnisse legten nahe:

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 

ich:

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

Ich denke, der einzige Weg, ich um dieses haben Begegnen zu vermeiden in einem UserControl als Parameter.

Antwort

1

Ich weiß nicht, warum das passiert, aber ich weiß, dass UserControl in VB6 halb Magie sind. Wenn Sie ein UserControl durch seinen tatsächlichen Typ in eine Funktion übergeben, verliert es alle seine UserControl-Basisklasse (ich weiß, VB6 hat keine Vererbung, aber beim Erstellen eines UserControl erwarten Sie bestimmte Features).

Also, wenn Sie

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

Sobald die Steuerung Ihrer Unterroutine verlässt, wird es als Steuer verhalten, nicht wie ein Usercontrol (Sie keinen Zugang mehr zu Usercontrol-Eigenschaften haben, und versucht, auf sie zuzugreifen wird einen Fehler verursachen). Sehr seltsame Fehler in VB6, und eine, die viel Haar zog, um es zu erarbeiten.

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

Und alles ist in Ordnung. Meine Vermutung ist, dass Sie richtig sind, und UserControls sind eingerahmt, nicht Controls nicht UserControls. Die einzige Lösung, Überprüfung zu geben, ist

TypeName() 

zu verwenden zu wissen, welche Art es ist, als dass nicht beschädigt bekommt.

+0

Wahrscheinlich am besten, dann versuche ich zu vermeiden, die Kontrolle als Parameter in erster Linie zu übergeben. Vielen Dank! – jpoh

1

Ich verwende VBControlExtender als Parametertyp

Public Sub SomeMethod(someControl as VBControlExtender)

dann bekomme ich die Referenzen wie diese

Dim someSpecificControl as SpecificControl 
Dim someSpecificControlExt as VBControlExtender 

Set someSpecificControl = someControl.object 
Set someSpecificControlExt = someControl

Dann someSpecificControlExt verwenden Left zuzugreifen, TabIndex, TabStop, Name, Move usw.Eigenschaften des Extenders und someSpecificControl für den Zugriff auf bestimmte Methoden/Eigenschaften meines Benutzersteuerelements.

Zu Ihrer Information, hängt das Verhalten Ihres Codes davon ab, ob das Benutzersteuerelement im aktuellen Projekt implementiert oder in einem OCX referenziert wird. Ich verwende Matt Curlands direct user control access hack auch, was mir diese

Dim someSpecificControl as DirectSpecificControl

so dass someSpecificControl Requisiten/Methoden zugegriffen werden erlaubt, zu tun früh gebundene.

Dies ist, wie ich someSpecificControlExt (der Extender) von der Steuerung erhalten:

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

Dies ist, wie ich die interne UserControl der VB6 Benutzerkontrolle erhalten:

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

Die Referenz GetUserControl kehrt hat eine sehr seltsame Umsetzung von QueryInterface - es scheint UserControl Schnittstelle ist speziell zu E_NOTIMPLEMENTED dummied.