Wie kann man eigentlich die in Visual Basic
"eingebauten" Steuerelemente (so genannte "Intrinsic
Controls") von externen Steuerelementen (OCXe) oder von per
UserControl-Modul selbst erstellten Steuerelementen unterscheiden?
Die Frage scheint sich auf den ersten Blick nicht so einfach
beantworten zu lassen. Aber wie Sie sich denken können, würde ich
nie eine solche Frage stellen, wenn ich nicht auch mit der Antwort
darauf aufwarten könnte.
Im Prinzip können Sie bei einem gegebenen Steuerelement mit TypeOf
eine Typprüfung vornehmen - also einfach alle in VB eingebauten
Objekt-Typen durchchecken:
If TypeOf IrgendeinControl Is CommandButton Then
...ist eingebaut
ElseIf TypeOf IrgendeinControl Is TextBox Then
...ist eingebaut
ElseIf ... usw.
Else
...ist NICHT eingebaut
End If
Oder Sie verknüpfen anstelle der ElseIf-Konstruktionen die
einzelnen Typprüfungen mit Or. Bis einschließlich Visual Basic 5
ist dies wohl auch der einzige gangbare Weg.
Ab Visual Basic 6 gibt es jedoch das VBControlExtender-Objekt.
Das heißt - eigentlich ist das kein eigenständiges Objekt, sondern
lediglich die Definition einer Schnittstelle, über die alle
Steuerelemente verfügen, die per Controls.Add
dynamisch der Controls-Collection eines Container-Objekts wie Form
oder UserControl hinzugefügt wurden. Und das gilt auch nur dann,
wenn es sich dabei nicht um eines der VB-eigenen Steuerelemente
handelt.
Sie ahnen bereits, worauf das hinausläuft? Genau, ein einfacher
Versuch zeigt, dass alle nicht-eingebauten Steuerelemente immer
über die VBControlExtender-Schnittstelle verfügen, selbst dann,
wenn sie nicht erst zur Laufzeit per Ihrem Code dynamisch geladen
worden sind, sondern bereits von Ihnen zur Design-Zeit auf einem
Objekt-Container platziert worden sind. Zum einen kann man daraus
darauf schließen, dass VB selbst zum Laden nicht-eingebauter
Steuerelemente den gleichen, seit VB 6 neuen Mechanismus verwendet,
der hinter dem dynamischen Laden steckt.
Zum anderen ergibt sich daraus ein einfaches Verfahren zur
Prüfung, ob es sich bei einem Steuerelement entweder um eines der
eingebauten handelt, oder ob es sich um ein externes OCX bzw. um ein
projektinternes UserControl handelt. So können Sie versuchen, ein
Steuerelement einer als VBControlExtender deklarierten
Objekt-Variablen zuzuweisen. Ein nicht-eingebautes Steuerelement
wird akzeptiert, wohingegen bei einem eingebauten Steuerelement ein
Laufzeitfehler ausgelöst wird. Fangen Sie diesen Laufzeitfehler ab,
können Sie den gewünschten Schluss über die Natur des
betreffenden Steuerelements ziehen - zum Beispiel in einer
praktischen Funktion gekapselt:
Public Function IsIntrinsicControl(Ctl As Control) As Boolean
Dim nVBCtlEx As VBControlExtender
On Error Resume Next
Set nVBCtlEx = Ctl
IsIntrinsicControl = CBool(Err.Number)
End Function
Falls Sie aus irgendeinem Grund die in einem Container-Objekt
vorhandenen eingebauten bzw. nicht-eingebauten Steuerelemente
zählen möchten, übergeben Sie einer der beiden folgenden
Funktionen einfach die Controls-Collection dieses Containers:
Public Function CountIntrinsicControls(Ctls As Object) As Integer
Dim nCtl As Control
Dim nCtlEx As VBControlExtender
Dim i As Integer
On Error Resume Next
For Each nCtl In Ctls
Set nCtlEx = nCtl
If Err.Number Then
Err.Clear
i = i + 1
End If
Next
CountIntrinsicControls = i
End Function
Public Function CountNonIntrinsicControls(Ctls As Object) As Integer
Dim nCtl As Control
Dim nCtlEx As VBControlExtender
Dim i As Integer
On Error Resume Next
For Each nCtl In Ctls
Set nCtlEx = nCtl
If Err.Number Then
Err.Clear
Else
i = i + 1
End If
Next
CountNonIntrinsicControls = i
End Function
Allerdings mag Sie die tatsächliche Anzahl wohl weniger
interessieren, als eher die Antwort auf die Frage, ob sich
überhaupt ein eingebautes bzw. ein nicht-eingebautes Steuerelement
in einem Container-Objekt befindet. Das Zählverfahren lässt sich
dazu abkürzen - bei den folgenden Funktionen gibt jeweils der erste
passende Fund True zurück und die Suchschleife wird abgebrochen.
Public Function AnyIntrinsicControls(Ctls As Object) As Boolean
Dim nCtl As Control
Dim nCtlEx As VBControlExtender
On Error Resume Next
For Each nCtl In Ctls
Set nCtlEx = nCtl
If Err.Number Then
AnyIntrinsicControls = True
Exit Function
End If
Next
End Function
Public Function NoIntrinsicControls(Ctls As Object) As Boolean
Dim nCtl As Control
Dim nCtlEx As VBControlExtender
On Error Resume Next
For Each nCtl In Ctls
Set nCtlEx = nCtl
If Err.Number Then
Err.Clear
Else
NoIntrinsicControls = True
End If
Next
End Function
|