In VB verwendet man den Zugriff auf Bits nur selten, z.B. bei der Belegung von 'Flag'-Variablen; aber selbst da gibt es die entsprechend benannten VB-Konstanten, durch die das richtige Bitmuster in den Flag-Parameter eintragen wird. Insofern ist die Beschäftigung mit Bits für VB-Programmierer eher uninteressant. Trotzdem sollte man auch mit Bits umgehen können, weil sie die 'informationelle' Basis der Operationen bilden. VB verfügt über bitweise arbeitende Operatoren (AND, EQV, IMP, OR). In Kombination mit dem NOT-Operator lassen sich die Bitmuster von zwei Variablen auf alle denkbaren Arten kombinieren. (Der XOR-Operator entspricht der Negation der EQV-Verknüpfung.) Was es in VB aber nicht gibt, sind Funktionen, durch die man direkt einzelne Bits in einer Variable abfragen, setzen oder löschen kann. Das Modul 'modBit' enthält deshalb die Funktion 'Ist_Bit_Gesetzt' zurAbfrage eines einzelnen Bits. Die Funktion 'Setze_Bit' setzt ein Bit und die Funktion 'Lösche_Bit' löscht ein Bit, falls es gesetzt ist. Dabei ist natürlich jeweils die Angabe der Position des Bit in der Variable erforderlich. Die Position 1 bezieht sich dabei auf das 'linke' Bit. Das Modul unterstützt die internen ganzzahligen VB-Variablentypen BYTE (8 Bit), INTEGER (16 Bit), LONG (32 Bit) und den nur als Untertyp von VARIANT implementierten Datentyp DECIMAL (96 Bit). Für 'Setze_Bit' und 'Lösche_Bit' gilt: Details: Die Bit-Operatoren in VB unterstützen nur Werte im Geltungs-Bereich des VB-Datentyps LONG. Für den Zugriff auf das in der VARIANT-Variable enthaltene 96-Bit-Muster des Untertyps DECIMAL muss deshalb eine Byte-Kopie in einen geeigneten UDT durchgeführt werden. Die dezimale Darstellung der VB-Datentypen ist gegenüber dem zugrundeliegenden binären Muster jeweils verschoben, damit INTEGER- und LONG-Variable auch negative Werte enthalten können. Aus diesem Grund sind datentypspezifische Hilfsfunktionen erstellt worden, die diese Transformationen berücksichtigen. Die Verschiebung beim Datentyp DECIMAL scheint technisch bedingt zu sein. Von der Manipulation von Bits in Gleitkommazahlen (IEEE-Format) ist abzuraten, weil die einzelnen Bitpositionen spezifische Bedeutungen bei der Verarbeitung der binären Muster besitzen (Interpretation als Exponentialdarstellung). Nicht alle Bitmuster sind auch gültig und definiert. Es kann u.a. zu Überlauf-Fehlern kommen. Variablen des Datentyps BOOLEAN sind 16 Bit lang. Bei der Belegung mit 'true' sind alle Bits gesetzt (entspricht als Integer: -1), bei der Belegung mit 'false' sind alle Bits gelöscht (entspricht als Integer: 0). Jede Zuweisung eines Integer-Wertes <> 0 auf eine boolsche Variable erzeugt den Wert 'true'. Die Manipulation von Bits in einer boolschen Variable ist deshalb nicht sinnvoll. Anwendung: Angenommen, ein Formular enthält ein Checkbox-Steuerelementefeld 'chkParameter', das maximal 32 Elemente umfasst. Der folgende Code zeigt, wie die Einstellungen der Boxen in eine Flag-Variable (LONG) übertragen und abgefragt werden. ' ================================================================== Dim i As Byte ' Loop Dim flags As Long ' Flag-Variable (LONG) Dim bs As String ' Flag-String (Demo) ' Einstellungen in Flag-Variable eintragen flags = 0 ' alle Flags sind gelöscht For i = 0 To chkParameter.Count - 1 If chkParameter(i).Value = vbChecked Then flags = Setze_Bit(flags, i + 1) End If Next i ' Flag-Variable abfragen (z.B. in der gerufenen Prozedur) bs = String(32, ".") For i = 1 To 32 If Ist_Bit_Gesetzt(flags, i) Then Mid$(bs, i, 1) = "1" End If Next i MsgBox "Flag-Variable: " + CStr(flags) + vbCrLf + bs ' ============================================================= ' ============================================================ ' Start Quellcode Modul: modBit ' ============================================================ Option Explicit ' Modul zum Abfragen, Setzen und Löschen von Bits ' in Variablen des Typs BYTE, INTEGER, LONG, Variant/DECIMAL ' Verwendung der Bit-Operatoren AND, OR, XOR ' und von 2-er Potenzen ' Übersicht über die Bit-Operatoren in VB ' ======================================= ' Variable Ergebnis log. Operator ' V1 V2 AND EQV IMP OR XOR ' ---------------------------------- ' 0 0 0 1 1 0 0 ' 0 1 0 0 1 1 1 ' 1 0 0 0 0 1 1 ' 1 1 1 1 1 1 0 ' Operator NOT kehrt Bit um ' V1 V2 NOT AND NOT IMP NOT OR ' ----------------------------------- ' 0 0 1 0 1 ' 0 1 1 0 0 ' 1 0 1 1 0 ' 1 1 0 0 0 ' c = a XOR b entspricht: c = NOT (a EQV b) ' Für das Kopieren eines Decimal-Wertes in 3 Long-Werte ' (incl. Verwaltungsbytes) Private Type Dec_Long Typ As Integer Nz As Byte Vz As Byte l(2 To 4) As Long End Type ' Kopieren von Bytefolgen ' verwendet für das Kopieren eines Decimal-Wertes in 4 Long-Werte Private Declare Sub CopyMemory Lib "kernel32" _ Alias "RtlMoveMemory" ( _ ByVal destination_pointer As Long, _ ByVal source_pointer As Long, _ ByVal bytes As Long) Public Function Setze_Bit(ByVal arg As Variant, _ ByVal bitpos As Byte) As Variant ' Bit an Position 'bitpos' der Variable 'arg' setzen, ' falls nicht gesetzt und Datentyp unterstützt If VarType(arg) = vbByte Then Setze_Bit = Setze_Bit_Byte(arg, bitpos) ElseIf VarType(arg) = vbInteger Then Setze_Bit = Setze_Bit_Integer(arg, bitpos) ElseIf VarType(arg) = vbLong Then Setze_Bit = Setze_Bit_Long(arg, bitpos) ElseIf VarType(arg) = vbDecimal Then Setze_Bit = OpBit_Decimal(arg, bitpos, 1) Else ' nicht unterstützter Typ ' ---> unveränderte Rückgabe Setze_Bit = arg End If End Function Public Function Lösche_Bit(ByVal arg As Variant, _ ByVal bitpos As Byte) As Variant ' Bit an Position 'bitpos' der Variable 'arg' löschen, ' falls gesetzt und Datentyp unterstützt If VarType(arg) = vbByte Then Lösche_Bit = Lösche_Bit_Byte(arg, bitpos) ElseIf VarType(arg) = vbInteger Then Lösche_Bit = Lösche_Bit_Integer(arg, bitpos) ElseIf VarType(arg) = vbLong Then Lösche_Bit = Lösche_Bit_Long(arg, bitpos) ElseIf VarType(arg) = vbDecimal Then Lösche_Bit = OpBit_Decimal(arg, bitpos, 2) Else ' nicht unterstützter Typ ' ---> unveränderte Rückgabe Lösche_Bit = arg End If End Function Public Function Ist_Bit_Gesetzt(ByVal arg As Variant, _ ByVal bitpos As Byte) As Boolean ' Bit an Position 'bitpos' der Variable 'arg' abfragen ' True: Bit ist gesetzt ' False: Bit nicht gesetzt oder falsche 'Bitpos' If VarType(arg) = vbByte Then Ist_Bit_Gesetzt = Ist_Bit_Gesetzt_Byte(arg, bitpos) ElseIf VarType(arg) = vbInteger Or VarType(arg) = vbBoolean Then Ist_Bit_Gesetzt = Ist_Bit_Gesetzt_Integer(arg, bitpos) ElseIf VarType(arg) = vbLong Then Ist_Bit_Gesetzt = Ist_Bit_Gesetzt_Long(arg, bitpos) ElseIf VarType(arg) = vbDecimal Then Ist_Bit_Gesetzt = OpBit_Decimal(arg, bitpos, 3) Else ' nicht unterstützter Typ ' ---> unveränderte Rückgabe Ist_Bit_Gesetzt = arg End If End Function Private Function Setze_Bit_Long(ByVal arg As Long, _ ByVal bitpos As Byte) As Long ' Setzt ein Bit an eine Position in Long-Variable ' Bitposition: 1 --> 32 (von links nach rechts) Const h As Long = -2 ^ 31 If bitpos > 32 Or bitpos < 1 Then Setze_Bit_Long = arg: Exit Function End If If bitpos = 32 Then arg = &H80000000 Or arg Else arg = (2 ^ (bitpos - 1)) Or arg End If Setze_Bit_Long = arg End Function Private Function Lösche_Bit_Long(ByVal arg As Long, _ ByVal bitpos As Byte) As Long ' Löscht ein Bit an einer Position in Long-Variable ' Bitposition: 1 --> 32 (von links nach rechts) Const h As Long = 2 ^ 31 - 1 ' 2147483647 If bitpos > 32 Or bitpos < 1 Then Lösche_Bit_Long = arg: Exit Function End If If bitpos = 32 Then arg = h And arg Else arg = ((2 ^ (bitpos - 1)) Xor CLng(-1)) And arg End If Lösche_Bit_Long = arg End Function Private Function Ist_Bit_Gesetzt_Long(ByVal arg As Long, _ ByVal bitpos As Byte) As Boolean ' Gibt True zurück, falls ein bestimmtes Bit gesetzt ist ' Bitposition: 1 --> 32 (von links nach rechts) If bitpos > 32 Or bitpos < 1 Then Exit Function Ist_Bit_Gesetzt_Long = False If bitpos = 32 Then Ist_Bit_Gesetzt_Long = arg And &H80000000 Else Ist_Bit_Gesetzt_Long = arg And (2 ^ (bitpos - 1)) End If End Function Private Function Setze_Bit_Integer(ByVal arg As Integer, _ ByVal bitpos As Byte) As Integer ' Setzt ein Bit an eine Position in Integer-Variable ' Bitposition: 1 --> 16 (von links nach rechts) If bitpos > 16 Or bitpos < 1 Then Setze_Bit_Integer = arg: Exit Function End If If bitpos = 16 Then ' falls das höchste bit gesetzt wird, ' muß der Integer ins Negative gedreht werden If arg >= 0 Then arg = (-32768 + arg) Else arg = (2 ^ (bitpos - 1)) Or arg End If Setze_Bit_Integer = arg End Function Private Function Lösche_Bit_Integer(ByVal arg As Integer, _ ByVal bitpos As Byte) As Integer ' Löscht ein Bit an einer Position in Integer-Variable ' Bitposition: 1 --> 16 (von links nach rechts) If bitpos > 16 Or bitpos < 1 Then Lösche_Bit_Integer = arg: Exit Function End If If bitpos = 16 Then ' falls das höchste bit gelöscht wird, ' muß der Integer ins Positive gedreht werden If arg < 0 Then arg = 32768 + arg Else arg = ((2 ^ (bitpos - 1)) Xor CInt(-1)) And arg End If Lösche_Bit_Integer = arg End Function Private Function Ist_Bit_Gesetzt_Integer(ByVal arg As Integer, _ ByVal bitpos As Byte) As Boolean ' Gibt True zurück, falls ein bestimmtes Bit gesetzt ist ' in Integer-Variable If bitpos > 16 Or bitpos < 1 Then Exit Function If bitpos = 16 Then ' Das höchste Bit ist gesetzt, wenn der Integer negativ ist Ist_Bit_Gesetzt_Integer = arg < 0 Else Ist_Bit_Gesetzt_Integer = arg And (2 ^ (bitpos - 1)) End If End Function Private Function Setze_Bit_Byte(ByVal arg As Byte, _ ByVal bitpos As Byte) As Byte ' Setzt ein Bit an eine Position in Byte-Variable ' Bitposition: 1 --> 8 (von links nach rechts) If bitpos > 8 Or bitpos < 1 Then Setze_Bit_Byte = arg: Exit Function End If Setze_Bit_Byte = (2 ^ (bitpos - 1)) Or arg End Function Private Function Lösche_Bit_Byte(ByVal arg As Byte, _ ByVal bitpos As Byte) As Byte ' Löscht ein Bit an einer Position in Byte-Variable ' Bitposition: 1 --> 8 (von links nach rechts) If bitpos > 8 Or bitpos < 1 Then Lösche_Bit_Byte = arg: Exit Function End If Lösche_Bit_Byte = ((2 ^ (bitpos - 1)) Xor CInt(-1)) And arg End Function Private Function Ist_Bit_Gesetzt_Byte(ByVal arg As Byte, _ ByVal bitpos As Byte) As Boolean ' Gibt True zurück, falls ein bestimmtes Bit gesetzt ist ' in Byte-Variable If bitpos > 8 Or bitpos < 1 Then Exit Function Ist_Bit_Gesetzt_Byte = arg And (2 ^ (bitpos - 1)) End Function Private Function OpBit_Decimal(ByVal arg As Variant, _ ByVal bitpos As Byte, _ ByVal op As Byte) As Variant ' Setzen, Löschen, Abfragen eines Bit in einer ' Variant/Decimal-Variable ' Bitposition: 1 bis 96 (von links nach rechts) Dim l As Dec_Long, Index As Byte If bitpos > 96 Or bitpos < 1 Then OpBit_Decimal = arg: Exit Function End If ' Variant/Decimal umkopieren l = Decimal_Nach_Long(arg) ' Long für BitPosition ermitteln If bitpos < 33 Then Index = 2 ElseIf bitpos < 65 Then Index = 3 bitpos = bitpos - 32 Else bitpos = bitpos - 64 Index = 4 End If If op > 2 Then ' Bit abfragen OpBit_Decimal = Ist_Bit_Gesetzt_Long(l.l(Index), bitpos) Else If op = 1 Then ' Bit setzen l.l(Index) = Setze_Bit_Long(l.l(Index), bitpos) Else ' Bit löschen l.l(Index) = Lösche_Bit_Long(l.l(Index), bitpos) End If ' Modifizierten Variant/Decimal zurückgeben OpBit_Decimal = Decimal_Von_Long(l) End If End Function Private Function Decimal_Nach_Long(ByVal arg As Variant) As Dec_Long ' Variant/Decimal wird in Verwaltung und 3 Longs kopiert If VarType(arg) <> vbDecimal Then Exit Function Dim l As Dec_Long Call CopyMemory(VarPtr(l), VarPtr(arg), 16) Decimal_Nach_Long = l End Function Private Function Decimal_Von_Long(ByRef l As Dec_Long) As Variant ' Verwaltung und 3 Longs werden in eine Variant-Variable kopiert Dim arg As Variant arg = CDec(0) Call CopyMemory(VarPtr(arg), VarPtr(l), 16&) Decimal_Von_Long = arg End Function ' ============================================================ ' Ende Quellcode Modul: modBit ' ============================================================ Dieser Tipp wurde bereits 28.577 mal aufgerufen. Voriger Tipp | Zufälliger Tipp | Nächster Tipp
Anzeige
Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv Vol.6 (einschl. Beispielprojekt!) Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m. |
sevAniGif (VB/VBA) Anzeigen von animierten GIF-Dateien Ab sofort lassen sich auch unter VB6 und VBA (Access ab Version 2000) animierte GIF-Grafiken anzeigen und abspielen, die entweder lokal auf dem System oder auf einem Webserver gespeichert sind. Tipp des Monats April 2024 Skyfloy Chart von Microsoft und dazu noch gratis Tutorial für Microsoft Chart Controls für Microsoft .NET Framework 3.5 Access-Tools Vol.1 Über 400 MByte Inhalt Mehr als 250 Access-Beispiele, 25 Add-Ins und ActiveX-Komponenten, 16 VB-Projekt inkl. Source, mehr als 320 Tipps & Tricks für Access und VB |
||||||||||||||||
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. |