Jump to content

Problem with doing simple operations with formated numbers inside an input


Recommended Posts

Hello. I come from: https://www.autoitscript.com/forum/topic/125747-ask-format-number-as-we-type/

One user was asking if it would be possible to give format to numbers as he was typping in an input.

He wanted to add a thousands separator (I know that there are a lot of examples around the forum, but this case was very interesting because he was asking about formatting in real time as the user enters data).

I want to create a simple data collection for my job. I don't need negative numbers or decimal places. I want that the user cant input how many pieces there were at the morning, how many at the night and perform a simple subtract :(

My goal is to do something like this:

1.png

 

This is a reduced copy of my code:

#include <WindowsConstants.au3>
#include <GUIConstants.au3>

Global $mainGUI = GUICreate("", 410, 75, -1, -1)
GUISetState(@SW_SHOW, $mainGUI)
WinSetOnTop($mainGUI, "", 1)

GUICtrlCreateLabel("Quantity at morning",5,8,130,33,$ES_CENTER)
Local $firstnumber = GUICtrlCreateInput("", 5, 30, 130, 35, BitOR($ES_NUMBER, $ES_CENTER))
GUICtrlSetFont(-1, 16, 700)
GUICtrlCreateLabel("Quantity at night",140,8,130,33,$ES_CENTER)
Local $secondnumber = GUICtrlCreateInput("", 140, 30, 130, 35, BitOR($ES_NUMBER, $ES_CENTER))
GUICtrlSetFont(-1, 16, 700)
GUICtrlCreateLabel("Pieces produced today",275,8,130,33,$ES_CENTER)
Local $lastnumber = GUICtrlCreateInput("", 275, 30, 130, 35, BitOR($ES_NUMBER, $ES_CENTER))
GUICtrlSetFont(-1, 16, 700)

GUIRegisterMsg($WM_COMMAND, "_WM_COMMAND")


While 1
    $msg = GUIGetMsg()

    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit

    EndSwitch

WEnd



Func _WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)

    Local $iIDFrom = BitAND($wParam, 0xFFFF);LoWord
    Local $iCode = BitShift($wParam, 16) ;HiWord
    Local $sDecimal = ""


    If $iIDFrom = $firstnumber And $iCode = $EN_CHANGE Then
        $sInput = GUICtrlRead($firstnumber)
        Local $Output = _StringAddThousandsSep($sInput)
        GUICtrlSetData($firstnumber, $Output)
    EndIf

    If $iIDFrom = $secondnumber And $iCode = $EN_CHANGE Then
        $sInput = GUICtrlRead($secondnumber)
        Local $Output = _StringAddThousandsSep($sInput)
        GUICtrlSetData($secondnumber, $Output)
        If GUICtrlRead($firstnumber) <> "" Then
            $first = GUICtrlRead($firstnumber)
            StringRegExpReplace($first, ".", ""); I remove the thousand separator from the string
            $second = GUICtrlRead($secondnumber)
            StringRegExpReplace($second, ".", "")
            $diff = Number($second) - Number($first)
            Local $Output = _StringAddThousandsSep($diff)
            GUICtrlSetData($lastnumber, $Output)
        EndIf
    EndIf

    If $iIDFrom = $lastnumber And $iCode = $EN_CHANGE Then
        $sInput = GUICtrlRead($lastnumber)
        Local $Output = _StringAddThousandsSep($sInput)
        GUICtrlSetData($lastnumber, $Output)
    EndIf

EndFunc   ;==>_WM_COMMAND


Func _StringAddThousandsSep($s_string, $i_convert_lcid = -1, $i_current_lcid = -1)
    ; $LOCALE_USER_DEFAULT = 0x0400
    If $i_current_lcid = -1 Or $i_current_lcid = Default Then $i_current_lcid = 0x0400
    If $i_convert_lcid = -1 Or $i_convert_lcid = Default Then $i_convert_lcid = 0x0400

    ; Get lcid decimal and thousands separators
    Local $t_buff_tmp = DllStructCreate("char[4]")
    DllCall("kernel32.dll", "int", "GetLocaleInfo", "int", $i_current_lcid, _
            "int", 0x0E, "ptr", DllStructGetPtr($t_buff_tmp), "int", 4)
    If @error Then Return SetError(1, 0, "")
    Local $s_cur_dec = DllStructGetData($t_buff_tmp, 1)

    DllCall("kernel32.dll", "int", "GetLocaleInfo", "int", $i_convert_lcid, _
            "int", 0x0E, "ptr", DllStructGetPtr($t_buff_tmp), "int", 4)
    If @error Then Return SetError(1, 0, "")
    Local $s_con_dec = DllStructGetData($t_buff_tmp, 1)

    DllCall("kernel32.dll", "int", "GetLocaleInfo", "int", $i_convert_lcid, _
            "int", 0x0F, "ptr", DllStructGetPtr($t_buff_tmp), "int", 4)
    If @error Then Return SetError(1, 0, "")
    Local $s_con_tho = DllStructGetData($t_buff_tmp, 1)

    ; For later formatting
    Local $i_number = StringRegExpReplace($s_string, "(\" & $s_cur_dec & "\d+\z)|(^-|\d+)|(\D)", "$2")
    Local $i_dec = StringRegExpReplace($s_string, "(.+?\" & $s_cur_dec & ")(\d+\z)", "$2")
    If @extended = 0 Then $i_dec = ""

    Local $i_str_len = StringLen($s_string) * 4
    Local $t_numberfmt = DllStructCreate("uint;uint;uint;ptr;ptr;uint")
    Local $t_thousands = DllStructCreate("wchar[2]")
    Local $t_decimal = DllStructCreate("wchar[2]")
    Local $t_buffer = DllStructCreate("wchar[" & $i_str_len & "]")

    DllStructSetData($t_thousands, 1, $s_con_tho)
    DllStructSetData($t_decimal, 1, $s_con_dec)
    DllStructSetData($t_numberfmt, 3, 3)
    DllStructSetData($t_numberfmt, 4, DllStructGetPtr($t_decimal))
    DllStructSetData($t_numberfmt, 5, DllStructGetPtr($t_thousands))
    DllStructSetData($t_numberfmt, 6, 1)

    DllCall("kernel32.dll", "int", "GetNumberFormatW", _
            "int", $i_convert_lcid, "int", 0, _
            "wstr", $i_number, "ptr", DllStructGetPtr($t_numberfmt), _
            "ptr", DllStructGetPtr($t_buffer), "int", $i_str_len)

    If $i_dec = "" Then $s_con_dec = ""
    Return DllStructGetData($t_buffer, 1) & $s_con_dec & $i_dec
EndFunc   ;==>_StringAddThousandsSep

Thanks to the examples in the forum it format the numbers to show on screen a point (".") as thousand separator in real time as I type in the inputs, but when I'm trying to perform a simple maths operation with numbers that use the separator the results are:

2.png

psyduck.png

Any idea or hint would be pretty much aprecciatted. I have tried to change the value of $i_convert_lcid = 0x0400 to spanish values and the result wans't better.

Any help or tip would be pretty apreciatted.

 

Greets from Barcelona

Link to comment
Share on other sites

You don't need a so complicated thing...
Please try this

#include <WindowsConstants.au3>
#include <GUIConstants.au3>

Global $mainGUI = GUICreate("", 410, 75, -1, -1)
GUICtrlCreateLabel("Quantity at morning",5,8,130,33,$ES_CENTER)
Local $firstnumber = GUICtrlCreateInput("", 5, 30, 130, 35, BitOR($ES_NUMBER, $ES_CENTER))
GUICtrlSetFont(-1, 16, 700)
GUICtrlCreateLabel("Quantity at night",140,8,130,33,$ES_CENTER)
Local $secondnumber = GUICtrlCreateInput("", 140, 30, 130, 35, BitOR($ES_NUMBER, $ES_CENTER))
GUICtrlSetFont(-1, 16, 700)
GUICtrlCreateLabel("Pieces produced today",275,8,130,33,$ES_CENTER)
Local $lastnumber = GUICtrlCreateInput("", 275, 30, 130, 35, BitOR($ES_READONLY, $ES_CENTER))
GUICtrlSetFont(-1, 16, 700)
GUICtrlSetBkColor(-1, 0xffffff)
GUISetState(@SW_SHOW, $mainGUI)

GUIRegisterMsg($WM_COMMAND, "_WM_COMMAND")


While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

;=============================================

Func _WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
    Local $iIDFrom = BitAND($wParam, 0xFFFF);LoWord
    Local $iCode = BitShift($wParam, 16) ;HiWord

 If $iCode = $EN_CHANGE Then
    If $iIDFrom = $firstnumber Then
        $sInput = GUICtrlRead($firstnumber)
        GUICtrlSetData($firstnumber, StringRegExpReplace(StringReplace($sInput, " ", ""), '(?<=\d)(?=(\d{3})+(?!\d))', " "))
    EndIf
    If $iIDFrom = $secondnumber Then
        $sInput = GUICtrlRead($secondnumber)
        GUICtrlSetData($secondnumber, StringRegExpReplace(StringReplace($sInput, " ", ""), '(?<=\d)(?=(\d{3})+(?!\d))', " "))
    EndIf

    $first = Number(StringReplace(GUICtrlRead($firstnumber), " ", ""))
    $second = Number(StringReplace(GUICtrlRead($secondnumber), " ", ""))
    If $second >= $first Then
        $diff = $second - $first
        GUICtrlSetData($lastnumber, StringRegExpReplace($diff, '(?<=\d)(?=(\d{3})+(?!\d))', " "))
    Else
        GUICtrlSetData($lastnumber, "0")
    EndIf
EndIf
    Return $GUI_RUNDEFMSG

EndFunc   ;==>_WM_COMMAND

 

Link to comment
Share on other sites

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

@Mikell, it worked like a charm. I just have to add the point to:

StringRegExpReplace(StringReplace($sInput, ".", ""), '(?<=\d)(?=(\d{3})+(?!\d))', "."))

to get what I needed.

I spent like 2 hours looking for examples, but I was more focused on the fact that there was going to be a huge difference due to the need of perform formating as I was typping :sweating:

 

Greets from Barcelona

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...