Jump to content
Sign in to follow this  
Clark

A little elegance required

Recommended Posts

Clark

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 this post


Link to post
Share on other sites
czardas

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

Share this post


Link to post
Share on other sites
Malkey

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 this post


Link to post
Share on other sites

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
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.