PDA

Vollständige Version anzeigen : Funktion des binären Systems bei Enumerationen


WeinGeist
08.09.2008, 13:14
Vielleicht hast du dich schon einmal gefragt wie es funktioniert, dass zum Beispiel für die MsgBox in Buttons mehrere Eigenschaften auf einmal angegeben werden können, zbsp: vbYesNo + vbInformation + vbDefaultButton2

Vielleicht hättest du das gleiche sogar selber schon gerne verwendet, hast aber nicht verstanden wie das eigentlich funktioniert. Im Grunde ist das relativ einfach, aber meistens hat man irgendwo nen "Knopf". Eine wirklich einfache erklärung habe ich leider auch noch nicht gefunden. ;) Ich versuche es mal mit einer auschweiffenden Variante.

Als einstieg etwas zum binären System un der Zählweise:
Im Prinzip muss man um es zu verstehen kurz das Hirn ausschalten und das ganze neu angehen, dann isses ganz einfach.

Am einfachsten kann man das binäre system mit den Fingern darstellen und hochzählen, das geschieht von Rechts nach Links. die Hand mit der Innenseite zu sich halten.
0000 = 0
0001 = 1 --> Daumen hoch
0010 = 2 --> Zeigefinger hoch
0011 = 3 --> Daumen und Zeigefinger hoch
0100 = 4 --> Mittelfinger hoch
0101 = 5 --> Mittelfinger und Daumen hoch
0110 = 6 --> Mittelfinger, Zeigefinger hoch
0111 = 7 --> Mittelfinger, Zeigefinger, Daumen hoch
1000 = 8 --> Ringfinger hoch
......
1111 = 15

Nun brauchen wir also, um 4 Bits (Stellen) aufzufüllen 4 Finger bzw. 15 Zähler. Sprich mit 4 Finger kann man maximal die Zahl 15 erreichen, was total 16 Positionen (inkl. 0) ergibt.

So geht das weiter und man kann immer weiter hochzählen, bis man alle Finger aufgebraucht hat. ;)
Mit einer Hand sind maximal 32 Position also maximal die Zahl 31 möglich (11111)


Wofür können wir das nun in den Enumerationen gebrauchen?

Als Einstieg mal die Enumeration der MsgBox:
'############################################################################### ##########################
'# Binäres System für Ausgabe-Bestimmung der MsgBox
'# -------------------------------------------------------------------------------------------------------
'# Wie die originale MsgBox ist auch die erweiterte mit einem binären Zahlensystem versehen welches
'# es erlaubt Buttons, Icon usw. durch addierung der verschiedenen Konstanten auszuwerten.
'#
'# -------------------------------------------------------------------------------------------------------
'# Buttons AND-Operator = 15 (1111)
'# -------------------------------------------------------------------------------------------------------
'# 0 0000 0000 ok
'# 1 0000 0001 ok abbr
'# 2 0000 0010 abbr retry ignore
'# 3 0000 0011 ja nein abbbr
'# 4 0000 0100 ja nein
'# 5 0000 0101 retry abbr
'# 6 0000 0110
'# 7 0000 0111
'# 8 0000 1000
'# 9 0000 1001
'# 10 0000 1010 1 user-knöpfe
'# 11 0000 1011 2 user-knöpfe
'# 12 0000 1100 3 user-knöpfe
'# 13 0000 1101 4 user-knöpfe
'# 14 0000 1110 5 user-knöpfe
'# 15 0000 1111 6 user-knöpfe
'#
'# -------------------------------------------------------------------------------------------------------
'# Bilder AND-Operator = 240 (1111 0000)
'# -------------------------------------------------------------------------------------------------------
'# 0 0000 0000 kein Bild
'# 16 0001 0000 Critical
'# 32 0010 0000 Question
'# 48 0011 0000 Exclamation
'# 64 0100 0000 Information
'#
'# -------------------------------------------------------------------------------------------------------
'# DefaultButtons AND-Operator = 3840 (1111 0000 0000)
'# -------------------------------------------------------------------------------------------------------
'# 0 0000 0000 0000 Default 1
'# 256 0001 0000 0000 Default 2
'# 512 0010 0000 0000 Default 3
'# 768 0011 0000 0000 Default 4
'# 1024 0100 0000 0000 Default 5
'# 1280 0101 0000 0000 Default 6
'#
'# -------------------------------------------------------------------------------------------------------
'# ModalType AND-Operator = 61440 (1111 0000 0000 0000)
'# -------------------------------------------------------------------------------------------------------
'# 0 0000 0000 0000 0000 ModalApp
'# 4096 0001 0000 0000 0000 ModalSystem
'#
'############################################################################### ##########################


Wie man unschwer erkennen kann, weisen die Verschiedenen Optionen, wenn man sie binär darstellt, gewisse Ähnlichkeiten auf. Pro Gruppe bleiben nämlich immer die einzelnen Stellen von vorherigen Gruppen auf 0. Aber warum?

Wenn man nun eine Zahl (Enumerationen wie vbYesNo sind nichts anderes als Zahlen im Hintergrund) mit der Maximal möglichen Zahl welche in einem solchen Block möglich sind, mittels "And" vergleicht, ergeben sich gemeinsamkeiten. Sind keine vorhanden ergibt das 0. Für das Ergebnis werden lediglich jene Bits (Stellen) gezählt, welche identisch sind.

Mit 4 Blöcken ist maximal die Zahl 15 möglich. also vergleiche ich eine x-beliebige Zahl zum Beispiel 0011 (3) mit 1111 (15), die ersten beiden ziffern (von rechts gesehen) sind identisch, also ergibt es die Zahl drei.

3 AND 15 = 3


Nun nehme ich einmal eine grössere Zahl, zbsp. 17 und vergleiche sie wiederum mit 15.

17 entspricht binär folgendem: 0001 0001. wenn ich das nun mit 15 (1111) vergleiche ergibt sich bei der ersten Zahl des Blocks 1 (immer von rechts gesehen) eine Übereinstimmung. Da lediglich im ersten Block eine Übereinstimmung vorhanden sein kann ist maximal die Zahl 15 möglich, hier ist nur die erste identisch, also ist das Ergebnis von "17 AND 1" 0001 was wiederum umgewandelt einer 1 entspricht.

Wenn ich nun 17 (0001 0001) mit 240 (1111 0000) vergleiche dann ist nur die 1 des zweiten blocks (wieder von rechts) identisch, folglich bekomme ich als ergebnis (0001 0000) was der Zahl 16 entspricht.

Diese Eigenschaft kann man sich nun zu nutze machen um Zahlen im Binärsystem eindeutig zu trennen. Sprich man erstellt Zahlengruppen und fasst sie zusammen. Zur unterscheidung fasst man sie in Blöcke.

Man nimmt für die erste gruppe zum beispiel zahlen von 1-15, also einen viererblock. Für eine zweite Gruppe nimmt man Zahlen ab 16, allerdins keine einzige welche binär dargestellt im ersten block irgendwann eine 1 bekommen könnte. Das wären bei verwendung von zwei blocks maximal die Zahl 240. Wobei diese Zahl alle in der 16er Reihe vorkommen 0001 0000= 16 verglichen mit 15 (1111) ergibt das 0000 = 0
0010 0000= 32 verglichen mit 15 (0000) ergibt das 0

Vergleicht man aber 16 (0001 0000) oder 32 (0010 0000) mit 240 (1111 0000) ergeben sich bei beiden Zahlen im zweiten block von Rechts übereinstimmungen, nicht jedoch im ersten Block.

Was bringt uns nun diese Erkenntnis?
Durch die Gruppierung sind wir in der Lage summen, welche aus unterschiedlichen Zahlen aus unterschiedlichen Gruppen bestehen, eindeutig aufschlüsseln. Um bei unserem Beispiel der Messagebox zu bleiben für die Buttons:
vbYesNo (4) + vbinformation (64) + vbDefaultbutton2(256) = 324

Binär dargestellt heisst das: 0001 0100 0100

Wollen wir nun in einem Code herausfinden was genau wir gewählt haben, dann wenden wir vorhergehende Methode an.


Für die Buttons zum Klicken:
324 AND 15
oder binär ausgedrückt: 0001 0100 0100 AND 1111

Jetzt fällt uns folgendes auf, von rechts gesehen ist im ersten block ist als einzige das dritte Bit in 15 und auch 324 bei beiden vorhanden. Alle anderen Positionen sind unterschiedlich.

Das Ergebnis ist also: 0100 was der Zahl 4 entspricht oder eben vbYesNo

Für die Images:
Hier sind wir mittlerweile im zweiten 4er block angelangt. Deshalb vergleichen wir 324 mit 240.

Binär ausgedrückt: 0001 0100 0100 AND 1111 0000

Auch hier fällt uns sofort auf, das im ersten block von rechts keinerlei übereinstimmung vorhanden ist. Im Zweiten Block das dritte Bit gleich ist. Der Dritte Block nach wie vor irrelevant.

Das Ergebnis ist also: 0100 0000 was in Zahlen ausgedrückt 64 entspricht oder eben vbInformation

Für den DefaultButton:
Hier ist der Vergleich mit dem dritten Block relevant. Wir vergleichen die maximale mögliche Zahl, also 3840 was binär 1111 0000 0000 entspricht, mit 340.

Binär ausgedrückt: 0001 0100 0100 AND 1111 0000 0000

Das Ergebnis lautet: 0001 0000 0000, was wiederum in Zahlen ausgedrückt 256 ergibt, was wiederum vbDefaultButton2 entspricht.

Wie ihr sieht, ist das eigentlich nicht allzu schwer.

Wie das ganze in der Praxis funktioniert, kann man auch gut in meiner Beispieldatei über die MsgBoxEx anschauen welche vor ein paar Jahren mal bei AccessGuru verfügbar war allerdings da schon von einem unbekannten Author.

Hier gehts zum CodeArchiv-Thread (http://www.ms-office-forum.net/forum/showthread.php?t=237488)

Für was ich das zum Beispiel noch brauche in der Praxis: Eine ErrorHandling Funktion, wo ich verschiedenste Gruppierungen, Log-Funktionen sowie Debug.Print und Messageboxes verwende. Per Funktion sezte ich die Standardwerte in der Anwendung. Je nach Anmeldungstyp, ErrorTyp und Standardeinstellung werden verschiedene Ausgabe-Funktionen für einen Error ausgeführt. In der Entwicklung zum beispiel hauptsächlich debug.print.

Gleichzeitig kann man die entsprechenden Einstellungen auch zur Laufzeit vornehmen. Um schnell zu testen wie es sich für den Benutzer ansieht.

Eine entsprechende Beispieldatei wird auch irgendwann folgen. ;)

Hoffe ich konnte einigen, bei welchen der Groschen noch nicht ganz gefallen ist das "rote Tuch" einigermassen verständlich erklären. Wodurch aussagen von zbsp. Joseph
If (RstOptions And dbSeeChanges) = 0 Then
RstOptions = RstOptions + dbSeeChanges
End If
Nicht mehr Kryptisch erscheinen. ;)
--> Anmerkung, hier wird überprüft ob in den Optionen dbSeeChanges angegeben worden ist, falls nein, wird es zu den Optionen hinzugefügt. ;)

Schöne Grüsse

ANHANG: Ein paar kleine Hilfsfunktionen - Autor weiss ich leider nicht mehr :(
'##### Binäre Zählen #####
'Byte in Binär:
Public Function BinByte(ByVal Value As Byte) As String
Dim I As Long

BinByte = String$(8, "0")

I = 15
Do While Value
If Value And 1 Then MidB$(BinByte, I) = "1"
Value = Value \ 2
I = I - 2
Loop
End Function

'Integer in Binär:
Public Function BinInt(ByVal Value As Integer) As String
Dim I As Long

BinInt = String$(16, "0")
If Value And &H8000 Then
'negatives Vorzeichen beachten:
MidB$(BinInt, 1) = "1"
Value = Value Xor &H8000
End If

I = 31
Do While Value
If Value And 1 Then MidB$(BinInt, I) = "1"
Value = Value \ 2
I = I - 2
Loop
End Function

'Long in Binär:
Public Function BinLng(ByVal Value As Long) As String
Dim I As Long

BinLng = String$(32, "0")
If Value And &H80000000 Then
'negatives Vorzeichen beachten:
MidB$(BinLng, 1) = "1"
Value = Value Xor &H80000000
End If

I = 63
Do While Value
If Value And 1 Then MidB$(BinLng, I) = "1"
Value = Value \ 2
I = I - 2
Loop
End Function

Sascha Trowitzsch
22.01.2009, 13:15
Hi,

Was ich nicht korrekt finde: Die Konstanten werden bei dir arithmetisch addiert, nicht logisch (Boolesch) - obwohl du ja dann die Maskierung mit AND auflöst.
Besser finde ich die Verknüpfung per OR:
RstOptions = RstOptions Or dbSeeChanges

Ciao, Sascha

WeinGeist
22.01.2009, 13:40
Hallo Sascha,

Vielen Dank für den Input.

Du hast natürlich recht, der OR Operator wäre für Binäre Additionen besser geeigent. Ist auch gut für Fehlerprävention sofern man doppelt zuweist. Erspart bei immer gewollt gesetztem Attribt auc zwei Zeilen Code. :)

Sollte man den Artikel eventuale entsprechend anpassen?

Grüsse

Sascha Trowitzsch
22.01.2009, 13:49
Sollte man den Artikel eventuale entsprechend anpassen?
Och, ...
Ich denke, dass mit diesen beiden zusätzlichen Beiträgen reicht.
Normal geht ja, wenn die Enumerationskonstanten 2er-Potenzen sind, auch nichts schief. Und Konstanten, die keine 2er-Potenzen sind, lassen sich nunmal nicht sinnvoll kombinieren. ;)

Ciao, Sascha