Rubrik: Variablen/Strings | VB-Versionen: VB2005, VB2008 | 12.01.09 |
Enumerationen als Bitfelder nutzen Dieser Tipp zeigt, wie man Enumerationen (Aufzählungen) als Bitfelder nutzen kann. | ||
Autor: Daniel Bühling | Bewertung: | Views: 10.487 |
www.mysldworks.de | System: Win2k, WinXP, Win7, Win8, Win10, Win11 | kein Beispielprojekt |
Angelehnt an den Tipp Elemente einer Enumeration ermitteln und zur Auswahl anzeigen möchte ich in diesem Tipp zeigen, wie man Enumerationen als Bitfelder nutzen kann.
Dazu stellen wir uns folgendes Beispiel eines Weckers vor:
In einem Dialog kann man Wochentage auswählen an denen der Wecker aktiv ist. Dabei ist jede Kombination möglich. Dies wird durch sieben CheckBoxen (Sonntag – Samstag) realisiert, wodurch sieben Boolean-Variablen entstehen. Für die weitere Verarbeitung soll aber nur eine Variable (Wochentag) verwendet werden.
Kommen wir zunächst zur Enumeration-Auflistung selbst:
<Flags()> Public Enum Wochentag Sonntag = 1 Montag = 2 Dienstag = 4 Mittwoch = 8 Donnerstag = 16 Freitag = 32 Samstag = 64 End Enum
Wichtig sind hier natürlich die Werte der jeweiligen Enumerationskonstanten in Potenzen von zwei, das heißt, 1, 2, 4, 8 usw. Dies bedeutet, dass sich die einzelnen Flags in kombinierten Enumerationskonstanten nicht überschneiden.
Das Flags Attribut ist nicht unbedingt notwendig, bietet jedoch unter anderem beim Umwandeln in einen String Vorteile.
Befüllt wird ein solches Bitfeld mit einer bitweisen OR-Kombination. Im beschrieben Beispiel könnte man die CheckBoxen wie folgt abfragen:
Private Function GetWochentag() As Wochentag Dim eWochentag As Wochentag If Me.chkSonntag.Checked Then eWochentag = eWochentag Or Wochentag.Sonntag End If If Me.chkMontag.Checked Then eWochentag = eWochentag Or Wochentag.Montag End If If Me.chkDienstag.Checked Then eWochentag = eWochentag Or Wochentag.Dienstag End If If Me.chkMittwoch.Checked Then eWochentag = eWochentag Or Wochentag.Mittwoch End If If Me.chkDonnerstag.Checked Then eWochentag = eWochentag Or Wochentag.Donnerstag End If If Me.chkFreitag.Checked Then eWochentag = eWochentag Or Wochentag.Freitag End If If Me.chkSamstag.Checked Then eWochentag = eWochentag Or Wochentag.Samstag End If Return eWochentag End Function
Die Enumerationsvariable Wochentag wird bei einer ausgewählten CheckBox immer mit dem Endsprechenden Wochentag durch den Or erweitert.
Die Wochentage, welche in der Enumerationsvariable enthalten sind, können Sie mit einem AND Abfrage ermitteln. Hier der umgekehrte Vorgang um die CheckBoxen nach dem Inhalt der Enumerationsvariable zu aktivieren:
Private Sub SetWochentag(ByVal eWochentag As Wochentag) If (eWochentag And Wochentag.Sonntag) <> 0 Then Me.chkSonntag.Checked = True Else Me.chkSonntag.Checked = False End If If (eWochentag And Wochentag.Montag) <> 0 Then Me.chkMontag.Checked = True Else Me.chkMontag.Checked = False End If If (eWochentag And Wochentag.Dienstag) <> 0 Then Me.chkDienstag.Checked = True Else Me.chkDienstag.Checked = False End If If (eWochentag And Wochentag.Mittwoch) <> 0 Then Me.chkMittwoch.Checked = True Else Me.chkMittwoch.Checked = False End If If (eWochentag And Wochentag.Donnerstag) <> 0 Then Me.chkDonnerstag.Checked = True Else Me.chkDonnerstag.Checked = False End If If (eWochentag And Wochentag.Freitag) <> 0 Then Me.chkFreitag.Checked = True Else Me.chkFreitag.Checked = False End If If (eWochentag And Wochentag.Samstag) <> 0 Then Me.chkSamstag.Checked = True Else Me.chkSamstag.Checked = False End If End Sub
Durch das Flags Attribut kann man den Inhalt auch sehr einfach in das Direktfenster schreiben:
Dim eWochentag As Wochentag eWochentag = Me.GetWochentag() Debug.Print(eWochentag.ToString)
Wenn das Flags Attribut nicht gesetzt ist, wird nur der Bitwert in das Direktfenster geschrieben.
Das Beispiel mit dem Wecker und den CheckBoxen für die Wochentage lässt sich natürlich noch optimieren. Wenn Sie zum Beispiel in der Tag-Eigenschaft der CheckBoxen die entsprechende Enumerationskonstante hinterlegen ist eine Schleife möglich.
Um dies kurz zu zeigen wird im Load-Ereignis des Formular die Tag-Eigenschaft der ComboBoxen befüllt:
Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Load Me.chkSonntag.Tag = Wochentag.Sonntag Me.chkMontag.Tag = Wochentag.Montag Me.chkDienstag.Tag = Wochentag.Dienstag Me.chkMittwoch.Tag = Wochentag.Mittwoch Me.chkDonnerstag.Tag = Wochentag.Donnerstag Me.chkFreitag.Tag = Wochentag.Freitag Me.chkSamstag.Tag = Wochentag.Samstag End Sub
Zum Schluss nun noch eine optimierte Möglichkeit der Methoden Get- und SetWochentag:
Private Function GetWochentag2() As Wochentag Dim eWochentag As Wochentag Dim oCheckBox As Windows.Forms.CheckBox For Each oControl As Windows.Forms.Control In Me.Controls If TypeOf oControl Is Windows.Forms.CheckBox Then oCheckBox = CType(oControl, CheckBox) If oCheckBox.Checked Then eWochentag = eWochentag Or CType(oCheckBox.Tag, Wochentag) End If End If Next Return eWochentag End Function
Private Sub SetWochentag2(ByVal eWochentag As Wochentag) Dim oCheckBox As Windows.Forms.CheckBox For Each oControl As Windows.Forms.Control In Me.Controls If TypeOf oControl Is Windows.Forms.CheckBox Then oCheckBox = CType(oControl, CheckBox) If (eWochentag And CType(oCheckBox.Tag, Wochentag)) <> 0 Then oCheckBox.Checked = True Else oCheckBox.Checked = False End If End If Next End Sub