Jump to content
Sign in to follow this  
Mat

Mini calculator

Recommended Posts

Mat

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 :D )

Things to do:

* Function/Variable adder

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 $iAdv = IniRead (@ScriptDir & "\settings.ini", "Settings", "Advanced", 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)
      AdlibRegister ("_EmptyWorkingSet", 1000)

   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)
         GUICtrlCreateRadio ("Rad", 93, 144, 80, 20)
            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, "==", "=")
   If $iAdv Then
      $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"
         $qVal = GUICtrlRead ($qInp)
         $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 0x0000000E ; adv yes
            $iAdv = 1
         Case 0x0000000F ; adv no
            $iAdv = 0
         Case 0x02000011 ; dec
            $nRndVal = GUICtrlRead ($hDec)
         Case 0x00000015 ; deg
            $sDefAng = "deg"
         Case 0x00000016 ; rad
            $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

Func rad ($iDeg)
   Return $iDeg / ($pi/180)
EndFunc ; ==> rad

Func deg ($iRad)
   Return $iRad * ($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 this post


Link to post
Share on other sites
oMBRa

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

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

$iDeg should be $iRad

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


Link to post
Share on other sites
WideBoyDixon

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


Link to post
Share on other sites
Mat

thanks for the reply.

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


Link to post
Share on other sites
oMBRa

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


Link to post
Share on other sites
Mat

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


Link to post
Share on other sites
Mat

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


Link to post
Share on other sites
oMBRa

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


Link to post
Share on other sites
dmob

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


Link to post
Share on other sites
oMBRa

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

Share this post


Link to post
Share on other sites
Mat

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 :D

Edited by mdiesel

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.