Jump to content

# A little elegance required

## Recommended Posts

Hi there

I know how to solve this problem with brute force, but I like my code to have some elegance so thought I would seek some help. I am not very familiar with bitwise operations so am floundering a little.

A small part of my programme has four checkboxes, labelled \$cbImp[1-4]. Rather than store a binary on/off field four times I have used a bitwise operator to store all possible combinations (15) as a number, thusly:

```for \$item = 1 to 4
if GUICtrlRead(\$cbImp[\$item]) = \$GUI_CHECKED then \$temp[\$item]=2^(\$item-1)
Next
\$Impacts=BitOR(\$temp[1],\$temp[2],\$temp[3],\$temp[4])```

This works well and stores in the database in a single field a number which I can (in my head) read back and restore the checkboxes to their previous state.

However, I can't find an elegant way to handle the 15 combinations (each checkbox being checked or unchecked) [actually it might be 16 - doesn't matter] with a huge case statement or some such.

I know if I read in an odd number it will always mean that \$cbImp[1] will be checked. I know a number greater than 8 will mean that \$cbImp[4] will be checked, but the middle two numbers look difficult.

Any pointers? (I hope I explained this well enough)

##### Share on other sites

The function you are looking for is BitAnd.

```\$d_0001 = 1
\$d_0010 = 2
\$d_0100 = 4
\$d_1000 = 8

\$dFlag = BitOR(\$d_0010, \$d_0100)

If BitAND(\$dFlag, \$d_0001) = 1 Then MsgBox(0, "", "0001") ; False
If BitAND(\$dFlag, \$d_0010) = 2 Then MsgBox(0, "", "0010") ; True
If BitAND(\$dFlag, \$d_0100) = 4 Then MsgBox(0, "", "0100") ; True
If BitAND(\$dFlag, \$d_1000) = 8 Then MsgBox(0, "", "1000") ; False

; Check for both \$d_0100 and \$d_0010 in one line of code:
If BitAND(\$dFlag, 6) = 6 Then MsgBox(0, "", "0110") ; True

; To check if all four bits are set you would use:
If BitAND(\$dFlag, 15) = 15 Then MsgBox(0, "", "1111") ; False```
Edited by czardas

How about

##### Share on other sites

Here is an example that can check if a number of checkboxes are checked or unchecked.

```#include <GUIConstantsEx.au3>

Local \$sRes, \$iNumCBoxes = 15
Local \$iNum = Checkboxes(\$iNumCBoxes)

; Check if checkboxes are checked or unchecked from the sum of the checked checkboxes.
For \$item = 0 To \$iNumCBoxes - 1
If BitAND(2 ^ \$item, \$iNum) = 2 ^ \$item Then
; or
;If BitAND(2 ^ \$item, \$iNum) = BitShift(1, -\$item) Then
\$sRes &= \$item + 1 & " checked." & @CRLF
Else
\$sRes &= \$item + 1 & " un-checked." & @CRLF
EndIf
Next

MsgBox(0, "Results", \$sRes)

Func Checkboxes(\$iNumCB)
Local \$msg, \$cbImp[\$iNumCB], \$iSum
GUICreate("My GUI Checkboxes")

For \$item = 0 To \$iNumCB - 1
\$cbImp[\$item] = GUICtrlCreateCheckbox("CHECKBOX " & (\$item + 1), 10, 10 + (\$item * 25), 120, 20)
Next

GUISetState()

While 1
\$iSum = 0
\$msg = GUIGetMsg()

; Check if checkboxes are checked or unchecked. And, sum the checked checkboxes.
For \$item = 0 To \$iNumCB - 1
If BitAND(GUICtrlRead(\$cbImp[\$item]), \$GUI_CHECKED) = \$GUI_CHECKED Then \$iSum += 2 ^ \$item ; or BitShift(1, -\$item)
Next

If \$msg = \$GUI_EVENT_CLOSE Then ExitLoop
WEnd
Return \$iSum
EndFunc   ;==>Checkboxes```
##### Share on other sites

Thankyou people

czardas had the best answer for me.

Here is the code I used:

```for \$index = 1 to 4
\$text = 2^(\$index-1)
if BitAND(\$bResult[9],\$text) = \$text then GUICtrlSetState(\$cbImp[\$index],\$GUI_CHECKED)
Next```

## Create an account or sign in to comment

You need to be a member in order to leave a comment

## Create an account

Sign up for a new account in our community. It's easy!

Register a new account

## Sign in

Already have an account? Sign in here.

Sign In Now
• ### Recently Browsing   0 members

• No registered users viewing this page.
×

• Wiki

• Back

• #### Beta

• Git
• FAQ
×
• Create New...