# Mini calculator

## Recommended Posts

probably the most efficient bit of code I have ever written!! Basicly the final thing i've done after spending a long time with windows message codes. Theres some set on event for simple stuff, but most of the actual stuff is handled by message codes.

I say its powerful, becouse you can use any built in autoit maths functions, as well as a few I've added, and its really easy to add them too, all you need to do is include the function in the script, and add the name to the array! I was very tempted to add an easy way to add them, but decided against it.

other stuff:

Options: Click on the "=" sign to bring up the options menu. options are: AllowBool (you can put 1=2 and it will return false), Allow advanced functions (when no, you can only use basic operators.), and the round value. Any oter options can be done fairly easily by editing the script

I have also added mod to the basic operators (a%n). as fell as factorial (n!). != is changed to <>, ++ to +1, -- to -1. Also, 42b2 = 42 in base 2, as does 42b>2. b< does the opposite. Alternatively use the tobase and frombase functions (WBD )

Things to do:

code

```#NoTrayIcon

Opt ("GUIOnEventMode", 1)

Global Const \$Pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132851
Global \$aOps[27] = ["asin", "acos", "atan", "sin", "cos", "tan", "bitand", "bitnot", "bitor", "bitrotate", "bitshift", "fact", _
"bitxor", "ceiling", "exp", "floor", "log", "srandom", "round", "sqrt", "random", "abs", "rad", "deg", "tobase", "frombase"]

Global \$nBool = IniRead (@ScriptDir & "\settings.ini", "Settings", "AllowBool", 1)
Global \$nRndVal = IniRead (@ScriptDir & "\settings.ini", "Settings", "RoundVal", 2)
Global \$x = IniRead (@ScriptDir & "\settings.ini", "Settings", "x", -1)
Global \$y = IniRead (@ScriptDir & "\settings.ini", "Settings", "y", -1)
Global \$sDefAng = IniRead (@ScriptDir & "\settings.ini", "Settings", "DefAng", "deg")
If \$sDefAng = "rad" Then \$sDefAng = ""

If Not FileExists (@ScriptDir & "\settings.ini") Then
\$hFile = FileOpen (@ScriptDir & "\settings.ini", 2)
FileWrite (\$hFile, "[Settings]" & @CRLF & "AllowBool=1" & @CRLF & "Advanced=1" & @CRLF &  "RoundVal=2" & @CRLF & "x=-1" & _
@CRLF & "y=-1" & @CRLF & "DefAng=deg")
FileFlush (\$hFile)
EndIf

_MiniMode ()

Func _MiniMode ()
Global \$hMiniUI = GUICreate ("MDiesel's Calculator!!", 205, 20, \$x, \$y, 0x80000000, 0x00000008 + 0x00000080)
GUISetBkColor (0xDDE7FF)
GUICtrlSetDefBkColor (-2)

GUICtrlCreateicon ("Shell32.dll", 28, 188, 1, 16, 17, 0x0100)
GUICtrlSetCursor (-1, "IDC_HAND")
GUICtrlSetOnEvent (-1, "_EventClose")

GUICtrlCreateLabel ("|" & @CRLF & "||" & @CRLF & "|||" & @CRLF & "|||" & @CRLF & "|||" & @CRLF & "|||" & @CRLF & "|||" & @CRLF & "||" & @CRLF & "|", 0, 0, 5, 20, -1, 0x00100000)
GUICtrlSetFont (-1, 2)
GUICtrlSetCursor (-1, 9)

Global \$qInp = GUICtrlCreateInput ("", 7, 2, 100, 17, 2 + 16 + 128)
Global \$qVal = ""
GUICtrlCreateLabel ("=", 109, 2, 5, 17, 0x0100)
GUICtrlSetOnEvent (-1, "_Settings")
Global \$aInp = GUICtrlCreateInput ("", 116, 2, 70, 17, 2048)
GUICtrlSetBkColor (-1, 0xFFFFFF)

GUISetState (@SW_SHOW, \$hMiniUI)

\$aPos = WinGetPos (\$hMiniUI, "")
Global \$hSetUI = GUICreate ("Settings", 205, 172, \$aPos[0], \$aPos[1] + 20, 0x80880000, 0x00000088)
GUIRegisterMsg (0x0047, "_Moved")
GUIRegisterMsg (0x0111, "_Event")
GUISetBkColor (0xDDE7FF)
GUICtrlSetDefBkColor (-2)
GUICtrlCreateicon ("Shell32.dll", 255, 186, 3, 16, 17, 0x0100)
GUICtrlSetCursor (-1, "IDC_HAND")
GUICtrlSetOnEvent (-1, "_Settings")
GUICtrlCreateButton ("DirectEdit", 2, 2, 180, 20)
GUICtrlSetOnEvent (-1, "_EventSettingsEdit")
GUICtrlCreateGroup ("Allow Boolean Results?", 2, 24, 196, 35)
GUICtrlCreateRadio ("Yes", 8, 36, 80, 20)
GUICtrlSetState (-1, 1)
GUICtrlCreateRadio ("No", 93, 36, 80, 20)
If \$nBool = 0 Then GUICtrlSetState (-1, 1)
GUICtrlCreateGroup ("Allow advanced Functions?", 2, 60, 196, 35)
GUICtrlCreateRadio ("Yes", 8, 72, 80, 20)
GUICtrlSetState (-1, 1)
GUICtrlCreateRadio ("No", 93, 72, 80, 20)
If \$iAdv = 0 Then GUICtrlSetState (-1, 1)
GUICtrlCreateGroup ("Round to: ", 2, 96, 196, 35)
Global \$hDec = GUICtrlCreateInput (\$nRndVal, 8, 108, 80, 17)
GUICtrlSetLimit (-1, 2)
GUICtrlCreateUpDown (\$hDec)
GUICtrlSetLimit (-1, 99)
GUICtrlCreateLabel ("Decimal Places.", 93, 110, 80, 20)
GUICtrlCreateGroup ("Default Angle measurement", 2, 132, 196, 35)
GUICtrlCreateRadio ("Deg", 8, 144, 80, 20)
GUICtrlSetState (-1, 1)
If \$sDefAng = "rad" Then GUICtrlSetState (-1, 1)

While 1
Sleep (5000)
WEnd
EndFunc ; ==> Minimode

Func _Calculate (\$sCalc)
\$sCalc = StringStripWS (\$sCalc, 8)
\$sCalc = StringReplace (\$sCalc, "!=", "<>")
\$sCalc = StringReplace (\$sCalc, "++", "+1")
\$sCalc = StringReplace (\$sCalc, "--", "-1")
\$sCalc = StringReplace (\$sCalc, "==", "=")
\$sCalc = StringRegExpReplace (\$sCalc, "sqrt\(([^\)]*)\)", "\(\1\^0\.5\)")
\$sCalc = StringRegExpReplace (\$sCalc, "([0-9]*)!", "fact\(\1\)")
\$sCalc = StringRegExpReplace (\$sCalc, "([0-9]*)%([0-9]*)", "\(mod\(\1\,\2\)\)")
\$sCalc = StringRegExpReplace (\$sCalc, "([0-9]*)b>([0-9]*)", "\(tobase\(\1\,\2\)\)")
\$sCalc = StringRegExpReplace (\$sCalc, "([0-9]*)b([0-9]*)", "\(tobase\(\1\,\2\)\)")
\$sCalc = StringRegExpReplace (\$sCalc, "([0-9]*)b<([0-9]*)", "\(frombase\(\1\,\2\)\)")
\$sCalc = StringRegExpReplace (\$sCalc, "(sin\([^\)]*\))", \$sDefAng & "\(\1\)")
\$sCalc = StringRegExpReplace (\$sCalc, "(asin\([^\)]*\))", \$sDefAng & "\(\1\)")
\$sCalc = StringRegExpReplace (\$sCalc, "(cos\([^\)]*\))", \$sDefAng & "\(\1\)")
\$sCalc = StringRegExpReplace (\$sCalc, "(acos\([^\)]*\))", \$sDefAng & "\(\1\)")
\$sCalc = StringRegExpReplace (\$sCalc, "(tan\([^\)]*\))", \$sDefAng & "\(\1\)")
\$sCalc = StringRegExpReplace (\$sCalc, "(atan\([^\)]*\))", \$sDefAng & "\(\1\)")
For \$i = 0 to UBound (\$aOps) - 1
If StringRegExp (\$sCalc, \$aOps[\$i]) <> 0 Then
\$n = StringRegExp (\$sCalc, \$aOps[\$i] & "\(([^\)]*)\)", 3)
For \$x = 0 to UBound (\$n, 1) - 1
If StringInStr (\$n[\$x], ",") Then
\$nSplit = StringSplit (\$n[\$x], ",")
For \$s = 1 to \$nSplit[0]
\$n[\$x] &= Execute (\$nSplit[\$s])
Next
Else
\$n[\$x] = Execute (\$n[\$x])
EndIf
\$sCalc = StringReplace (\$sCalc, \$aOps[\$i] & "(" & \$n[\$x] & ")", Execute (\$aOps[\$i] & "(" & \$n[\$x] & ")"))
Next
ExitLoop
EndIf
Next
If StringInStr (\$sCalc, "mod") Then
\$n = StringRegExp (\$sCalc, \$aOps[\$i] & "\(([^\)]*)\)", 3)
For \$i = 0 to UBound (\$n, 1) - 1
\$sCalc = StringReplace (\$sCalc, \$aOps[\$i] & "(" & \$n[\$i] & ")", Execute (\$aOps[\$i]) & (Execute (\$n[\$i])))
Next
EndIf
\$sCalc = StringReplace (\$sCalc, "pi", \$Pi)
If StringRegExp (\$sCalc, "[:alpha:]*\([^\)]*\)") Then Return SetError (1, 0, "Unknown Function")
EndIf
If StringinStr (\$sCalc, "=") Or StringRegExp (\$sCalc, "[^b][<;>]") = 1 Then ; operator used, return bool
\$sCalc = Execute (\$sCalc)
If \$sCalc = 1 Then Return SetExtended (1, "True")
Return SetExtended (1, "False")
EndIf
Return Round (Execute (\$sCalc), \$nRndVal)
EndFunc ; ==> _Calculate

Func _Event (\$hWnd, \$msgId, \$lParam, \$wParam)
If \$hWnd = \$hMiniUI Then
If \$msgId = 273 And \$lParam = 0x04000005 Then
If StringRegExp (StringRight (GUICtrlRead (\$qInp), 1), "[^0-9;\);i;!]") Then Return "GUI_RunDefMsg"
If StringLen (StringRegExpReplace (GUICtrlRead (\$qInp), "[^\(]", "")) <> StringLen (StringRegExpReplace (GUICtrlRead (\$qInp), "[^\)]", "")) Then Return "GUI_RunDefMsg"
\$aVal = _Calculate (\$qVal)
If @Error <> 0 Then
MsgBox (16, "Error - " & @Error, \$aVal)
ElseIf @Extended <> 0 Then
If \$nBool Then
\$aVal = "BOOL: " & \$aVal
Else
GUISetState (@SW_HIDE, \$hMiniUI)
GUISetState (@SW_HIDE, \$hSetUI)
MsgBox (16, "Error - 42", "Incorrect input value: input contained =, < or >.")
GUICtrlSetData (\$qInp, "")
GUICtrlSetData (\$aInp, "")
GUISetState (@SW_SHOW, \$hMiniUI)
GUISetState (@SW_SHOW, \$hSetUI)
EndIf
EndIf
GUICtrlSetData (\$aInp, \$aVal)
EndIf
Else
Switch \$lParam
Case 0x0000000B ; bool yes
\$nBool = 1
Case 0x0000000C ; bool no
\$nBool = 0
Case 0x02000011 ; dec
Case 0x00000015 ; deg
\$sDefAng = "deg"
\$sDefAng = ""
EndSwitch
EndIf
Return "GUI_RunDefMsg"
EndFunc ; ==> _Event

Func _EventClose ()
\$aPos = WinGetPos ("MDiesel's Calculator!!", "")
\$hFile = FileOpen (@ScriptDir & "\settings.ini", 2)
FileWrite (\$hFile, "[Settings]" & @CRLF & "AllowBool=" & \$nBool & @CRLF & "Advanced=" & \$iAdv & @CRLF &  "RoundVal=" & _
\$nRndVal & @CRLF & "x=" & \$aPos[0] & @CRLF & "y=" & \$aPos[1] & @CRLF & "DefAng=" & \$sDefAng)
FileFlush (\$hFile)
Exit
EndFunc ; ==> _EventClose

Func _Settings ()
If BitAnd (WinGetState (\$hSetUI, ""), 2) Then
GUISetState (@SW_HIDE, \$hSetUI)
Else
GUISetState (@SW_SHOW, \$hSetUI)
EndIf
EndFunc ; ==> _Settings

Func _EventSettingsEdit ()
\$aPos = WinGetPos ("MDiesel's Calculator!!", "")
\$hFile = FileOpen (@ScriptDir & "\settings.ini", 2)
FileWrite (\$hFile, "[Settings]" & @CRLF & "AllowBool=" & \$nBool & @CRLF & "Advanced=" & \$iAdv & @CRLF & "RoundVal=" & _
\$nRndVal & @CRLF & "x=" & \$aPos[0] & @CRLF & "y=" & \$aPos[1] & @CRLF & "DefAng=" & \$sDefAng)
FileFlush (\$hFile)
ShellExecute (@ScriptDir & "\settings.ini")
EndFunc ; ==> _EventSettingsEdit

Func fact (\$iNum)
\$x = 1
For \$i = 1 to \$inum
\$x *= \$i
Next
Return \$x
EndFunc ; ==> fact

Return \$iDeg / (\$pi/180)

EndFunc ; ==> deg

Func tobase (\$iNumber, \$iBase, \$iPad = 1)
If \$iBase < 2 And \$iBase > 36 Then Return 0
Local \$sRet = "", \$iDigit
Do
\$iDigit = Mod (\$iNumber, \$iBase)
\$sRet = Chr (48 + \$iDigit + 7 * (\$iDigit > 9)) & \$sRet
\$iNumber = Int (\$iNumber / \$iBase)
Until (\$iNumber = 0) And (StringLen (\$sRet) >= \$iPad)
Return \$sRet
EndFunc ; ==> tobase

Func frombase (\$sNumber, \$iBase)
Local \$iRet = 0, \$sChar
Do
\$iRet *= \$iBase
\$sChar = StringLeft (\$sNumber, 1)
\$iRet += Asc (\$sChar) + 7 * (Asc(\$sChar) < 58) - 55
\$sNumber = StringMid (\$sNumber, 2)
Until \$sNumber = ""
Return \$iRet
EndFunc ; ==> frombase

Func _Moved (\$hWnd, \$msgID, \$lParam, \$wParam)
\$aPos = WinGetPos ("MDiesel's Calculator!!", "")
If \$aPos[1] > @DesktopHeight - 220 Then \$aPos[1] = \$aPos[1] - 193
WinMove (\$hSetUI, "", \$aPos[0], \$aPos[1] + 20)
EndFunc ; ==> _Moved

Func _EmptyWorkingSet ()
DllCall ("psapi.dll", "int", "EmptyWorkingSet", "long", -1)
EndFunc ; ==> _EmptyWorkingSet```

MDiesel

Edit: missed a line of code...

Edited by mdiesel
##### Share on other sites

Well done its a nice script! btw I found a minor error:

```Func deg (\$iRad)
Return \$iDeg * (\$pi/180)
EndFunc; ==> deg```

It would be good to use degree as well and not only rad with trigonometric (spelled right?) functions

EDIT: found another bugs(?) "++1" returns 11, same for --, 1++1 returns 12... and can you explain how to use tobase, frombase etc functions?

Edited by oMBRa
##### Share on other sites

```tobase (\$decimal, \$base, \$pad)
\$decimal = number to convert
\$base = base to convert to
\$pad = minimum number of characters in the output```

E.g.

`If tobase(255, 16, 4) = "00FF" Then MsgBox(64, "Test", "Working!")`

```frombase(\$number, \$base)
\$number = string representation of the number in base form (e.g. "00ff")
\$base = base that the number is encoded in```

E.g.

`If frombase("00FF", 16) = 255 Then MsgBox(64, "Test", "Working again!")`

HTH. WBD.

##### Share on other sites

Num B base is the syntax.

42b2 = 101010 (42 in base 2)

or it can be 42b>2

the > or < is a direction indicator.

101010b<2 = 42 (101010 from 2)

those are wbd's functions.. I did put that in the script... yer I did. Func tobase () ; WBD

radians and degrees aren't my strong point. possibly an option "default angle" and deg/rad.

it will probably be:

\$sCalc = StringRegExpReplace (\$sCalc, "(sin\([^\)]*\))", \$sDefAngle & "\(\1\)")

untested.

will do that then!

as for ++ and --

thats probably supposed to be 1++ = 2... I will have a proper look when I get back...

MDiesel

##### Share on other sites

```tobase (\$decimal, \$base, \$pad)
\$decimal = number to convert
\$base = base to convert to
\$pad = minimum number of characters in the output```

E.g.

`If tobase(255, 16, 4) = "00FF" Then MsgBox(64, "Test", "Working!")`

```frombase(\$number, \$base)
\$number = string representation of the number in base form (e.g. "00ff")
\$base = base that the number is encoded in```

E.g.

`If frombase("00FF", 16) = 255 Then MsgBox(64, "Test", "Working again!")`

HTH. WBD.

aaah, I thought I had to use it inside the input box to do the conversion, btw converting any number to any base > 9 results in a never ending loop, because it does the calc while you are typing so it does first 65 to base 1... you should modify the tobase function in order to do nothing if base is 1 Edited by oMBRa
##### Share on other sites

aaah yep, I have done that in other functions, but not in this one...

I am really struggling with this now... but I will post when I'm done

MDiesel

##### Share on other sites

done!! in the end I realised I was double converting when \$sDefAngle = "rad".

codeupdate in post 1 will follow shortly. (done)

I've got this running permanently now, and its doing well!!

MDiesel

Another edit. The settings and main gui's movements are now synced.

Edited by mdiesel
##### Share on other sites

the problem "tobase" is still here because if I want to convert e.g. 65 to base 16 I would type 65b1 but it says range exceeded thus I cant complete it and adding the missing "6", you should return without doing anything

##### Share on other sites

CODE
D:\Scripts\Calculator.au3(140,22) : WARNING: \$hMiniUI: possibly used before declaration.

If \$hWnd = \$hMiniUI Then

~~~~~~~~~~~~~~~~~~~~^

.. even though I see its declared in line 26.

##### Share on other sites

you should either do a beta run or declare all global variables outside the functions

##### Share on other sites

no error here, but I can see why. I was registering a message before the

should be fixed now.

????? thats really not right as I declare the message that calls the function after declaring the variable, so whatever gave you that warning is wrong in this case.

MDiesel

Edit: didn't see:

the problem "tobase" is still here because if I want to convert e.g. 65 to base 16 I would type 65b1 but it says range exceeded thus I cant complete it and adding the missing "6", you should return without doing anything

fixed

Edited by mdiesel

## Create an account

Register a new account

• ### Recently Browsing   0 members

×

• Wiki

• Back

• #### Beta

• Git
• FAQ
×
• Create New...