vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
vb@rchiv Offline-Reader - exklusiv auf der vb@rchiv CD Vol.4  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück

In diesem Forum haben Sie die Möglichkeit Kommentare, Fragen und Verbesserungsvorschläge zu den im vb@rchiv gelisteten Tipps und Workshops zu posten.

Hinweis:
Ein neues Thema kann immer nur über die jeweilige Tipps & Tricks bzw. Workshop Seite eröffnet werden!

 Sie sind aktuell nicht angemeldet.Funktionen: Einloggen  |  Neu registrieren  |  Suchen

Fragen zu Tipps & Tricks und Workshops im vb@rchiv
Workshop 97: "For...Each" individuell implementieren durch das IEnumVariant-Interface 
Autor: Dirk
 Workshop anzeigenDatum: 13.05.09 14:10

Ganz nett, aber buggy und teilweise unklar.

Erstmal ist nicht vernünftig erklärt, warum der VTable-Eintrag angepasst werden muss. Gut, wenn es nicht gemacht wird, crasht das Programm. Aber aus einem Crash leite ich nicht grundsätzlich ein VTable ummapen ab ;).

Ich habe versucht das Ganze in einer Collection ähnlichen Klasse einzusetzen und bin dabei auf ein paar Probleme gestoßen:

Das Ummappen der IEnumVariant_Next Funktion ist nicht sauber gelöst.

Wenn mehrere Objekte der Klasse instanziiert werden, und eines terminiert, wird der VTable Eintrag zurückgesetzt und danach crasht es.

Lösung:
Modul
Private m_MapCounter As Long
 
Public Function MapVTable( _
    ByVal ptrObject As Long, _
    ByVal vIndex As Long, _
    ByVal ptrNewProc As Long _
  ) As Long
 
  Dim VTblOffset As Long
  Dim VTblPtr As Long
  Dim OldPageProtect As VirtualAllocPageFlags
 
  ' get VTable pointer
  CopyMemory VTblPtr, ByVal ptrObject, 4
 
  ' offset to function
  VTblOffset = VTblPtr + (vIndex * 4)
 
  ' change r/w protection
  VirtualProtect VTblOffset, 4, PAGE_EXECUTE_READWRITE, OldPageProtect
 
  ' get pointer to current function
  CopyMemory MapVTable, ByVal VTblOffset, 4
 
  ' replace function pointer
  CopyMemory ByVal VTblOffset, ptrNewProc, 4
 
  ' reset r/w protection
  VirtualProtect VTblOffset, 4, OldPageProtect, OldPageProtect
 
  m_MapCounter = m_MapCounter + 1
 
End Function
 
Public Sub UnMapVTable( _
    ByVal ptrObject As Long, _
    ByVal vIndex As Long, _
    ByVal ptrNewProc As Long _
  )
 
  m_MapCounter = m_MapCounter - 1
 
  If m_MapCounter = 0 Then
    MapVTable ptrObject, vIndex, ptrNewProc
  End If
 
End Sub
Klasse:
Private Sub Class_Initialize()
 
  m_ptrOldVTableEntry = MapVTable(ObjtPtrMe, 3, AddressOf _
    IEnumVariantNext_Mapped)
 
End Sub
 
Private Sub Class_Terminate()
  Call UnMapVTable(ObjtPtrMe, 3, m_ptrOldVTableEntry)
 
End Sub
For Each kann nur benutzt werden, wenn die Klasse die NewEnum Property enthält.
Dann muss natürlich folgende Funktion in die "Collection" Klasse:
Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_MemberFlags = "40"
 
  Set NewEnum = Me
 
End Property
Dann muss natürlich die Funktion IEnumVariant_NextReDef entsprechend angepasst werden. Vielleicht für viele klar, aber auch für alle?? Hier mal mein Beispiel:
Private Function IEnumVariant_NextReDef( _
    ByVal celt As Long, _
    rgvar As Variant, _
    ByVal pceltFetched As Long _
  ) As IEnumVariantVB.NextRet
 
  If Me.Count > m_IEnumIndex Then
 
    If celt = 1 Then 'geht wahrscheinlich sowieso nicht anders seitens VB
      m_IEnumIndex = m_IEnumIndex + 1
      Set rgvar = Me.Item(m_IEnumIndex) 'meine Liste über die ich per Index 
      ' zugreife
      IEnumVariant_NextReDef = IEnumVariantVB.NextRet.S_OK
    Else
      Raise [Requested elements must be 1], "Next" 'interne Fehlerbehandlung, 
      ' hier unwichtig
    End If
 
  Else
    IEnumVariant_NextReDef = IEnumVariantVB.NextRet.S_FALSE
  End If
End Function
Da taucht auch gleich das nächste Problem auf. Beim nächsten For Each Durchlauf, wird m_IEnumIndex nicht zurückgesetzt. D.h. die Schleife wird nicht mehr durchlaufen. Ich dachte daher ein einfaches:
Private Sub IEnumVariant_Reset()
  m_IEnumIndex = 0
End Sub
würde helfen. Dies wird aber leider nicht aufgerufen. Verstehe ich nicht, wofür ist das dann überhaupt gut? Damit die für mich (momentan) finale Frage:

Wie erkenne ich, dass "For Each" initialisiert wird/werden muss?

Eine spontane Idee wäre, den m_IEnumIndex auf 0 zu setzen, wenn IEnumVariant_NextReDef = IEnumVariantVB.NextRet.S_FALSE erreicht ist. Bringt aber nix, ich kann for each ja vorzeitig verlassen --> Exit For.

Vielleicht hat ja jemand eine Lösung dafür ...

Gruß
Dirk

--
?Get it right the first time

alle Nachrichten anzeigenGesamtübersicht  |  Zum Thema  |  Suchen

 ThemaViews  AutorDatum
Workshop 97: "For...Each" individuell implementieren durch d...5.199Dirk13.05.09 14:10
Re: "For...Each" individuell implementieren durch das IEnumV...2.188Symundo17.09.09 11:17

Sie sind nicht angemeldet!
Um einen neuen Beitrag schreiben zu können, müssen Sie sich zunächst anmelden.

Einloggen  |  Neu registrieren

Funktionen:  Zum Thema  |  GesamtübersichtSuchen 

nach obenzurück
 
   

Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel