Numeric Entry in an EditBox

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
RNBW
Posts: 267
Joined: Apr 11, 2015 11:06
Location: UK

Numeric Entry in an EditBox

Post by RNBW »

I have listed this code already at viewtopic.php?f=8&t=24617&start=45 because I used Lothar Schirm's Simple Windows API Library. However, anyone searching for "Numeric Entry in an EditBox" may not find it there, so I am posting it under a more relevant heading.

There are many routines for restricting numeric entry into an editbox to numbers and ". and -", but I wanted something that would error check as you entered the characters one by one and would also display entries of ".123" as "0.123" and "-.123" as "-0.123". The routine would also have to ensure entry of only one "-" and this would be at the beginning of the number. The routine would also have to ensure that only one "." could be entered and it must also allow editing.

I believe the following code does this, so I hope it will be of use to anyone looking for this type of entry.

Code: Select all

'=============================================
'  NUMERIC INPUT IN A TEXTBOX
'  This does a check for 0-9 and - or . and prevents entry of all other
'  characters.   It ensures that "-" can only be placed at the start of
'  the number entry.  It also ensures that only one "." or "-"   can be
'  entered.
'  It also ensures that if .123 is entered it displays 0.123 and if
'  -.123 is entered -0.123 is displayed.
'  Code by RNBW.  
'============================================

#Include "WinGUI.bi"

Dim As HWND Window_Main, Button_Ok, Edit_1
Dim As MSG msg
dim As String txt, oldtxt
Dim As Integer pos0   


Function num(ByVal txt As String) As String
   'Function to check that character input is 0-9, - or .
   
   Dim As String num1
   Dim As Integer i, a, t
                                             
   For i = 1 To Len(txt)
      a = Asc(Mid(txt,i,1))
      if a = 46 then t = t + 1
        if (a = 46) and (t > 1) then a = 0    'only DOT after FIRST is cleared
        if a = 45 and i>1 then a = 0          'so really almost anything do, not just 8
        if a = 46 and i = 1 then num1 = "0" + num1
      If a = 45 Or a = 46 or a > 47 and a < 58 then num1 = num1 + Chr(a)
   Next
   
   a=asc(mid(txt,1,1))
    if a = 45 and mid(txt,2,1) = "." then num1 = "-0" + num1
   
   Return num1

End Function


'Create a window with an Editbox and a button:
Window_Main = Window_New   (100, 100, 400, 400, "Numeric Entry Filter!")
Var Label_txt = Label_New  (10, 10, 150, 20, "Enter numbers:",, Window_Main)
Edit_1 = EditBox_New       (150, 10, 100, 20, "",, Window_Main)
Button_Ok = Button_New     (160, 300, 60, 20, "Ok",, Window_Main)

'Set timer to 300 miliseconds:
SetTimer(Window_Main, 0, 300, 0 )

Do
   WaitEvent(Window_Main,msg)
   Select Case msg.message
      Case WM_TIMER
         'Check contents of the edit box every 300 millisecinds
         txt = EditBox_GetText(Edit_1)   'get text from edit box
         oldtxt = txt      'make text the oldtext
         txt = num(txt)  'gets new text from function num(txt) which does the checking
         If oldtxt <> txt Then
            EditBox_SetText(Edit_1, txt)   'if old text is not the same as the new text then use new text
            pos0 = Len(txt)   'position of character is the length of the current text
            SendMessage(Edit_1, EM_SETSEL, pos0, pos0)
         End If
      Case WM_LBUTTONDOWN
         If msg.hwnd = Button_Ok Then Print EditBox_GetText(Edit_1)  'print text to console
   End Select
Loop Until Window_Event_Close(Window_Main, msg)

End
RNBW
Posts: 267
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Post by RNBW »

I have found that not all IDEs produce a console window automatically, so clicking the OK button does not always print out the number entered in the Editbox on the console. I have modified the code to open a console window. Also I have modified the code to the Editbox so that the characters entered are right justified.

The modified code can be found here viewtopic.php?f=8&t=24617&start=45#p249046
bcohio2001
Posts: 556
Joined: Mar 10, 2007 15:44
Location: Ohio, USA
Contact:

Re: Numeric Entry in an EditBox

Post by bcohio2001 »

Just an idea or challenge.
Allow for "single precision" numbers.
Such as 6.02e-23
RNBW
Posts: 267
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Post by RNBW »

I think that it's quite a good idea. Hopefully, someone will take up the challenge. Let's have a competition to see who can come up with the best solution!
RNBW
Posts: 267
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Post by RNBW »

Having had a further look at the code myself, an Editbox is not really designed to hold all the digits in a single precision number. However, I have had a quick look at formatting the input using format(). You need to add

Code: Select all

#include "vbcompat.bi"
at the head of the code. The example I've shown will format the entry to 3 decimal places and show a 0 before the decimal point if this is the first digit. You can play around with the formatting to your heart's content. However, what I'm finding is that when you click in the Editbox "0." comes up. Sometimes this can be overtyped and sometimes you have to fiddle around with the entry to get it to work. Not very satisfactory! Any ideas?

Code: Select all

REM=============================================
'  NUMERIC INPUT IN A TEXTBOX
'  This does a check for 0-9 and - or . and prevents entry of all other
'  characters.   It ensures that "-" can only be placed at the start of
'  the number entry.  It also ensures that only one "." or "-"   can be
'  entered.
'  It also ensures that if .123 is entered it displays 0.123 and if
'  -.123 is entered -0.123 is displayed.
'  Characters entered are right justified
'  Code by RNBW.  
'============================================

#INCLUDE "WinGUI.bi"
#include "VBcompat.bi"

DIM AS HWND Window_Main, Button_Ok, Edit_1
DIM AS MSG msg
DIM AS STRING sTxt, oldsTxt, sNumFormat
DIM AS INTEGER pos0
   

FUNCTION sNum(BYVAL sTxt AS STRING) AS STRING
   'Function to check that character input is 0-9, - or .
   
   DIM AS STRING sNum1
   DIM AS INTEGER i, a, t
                                             
   FOR i = 1 TO LEN(sTxt)
      a = ASC(MID(sTxt,i,1))
      IF a = 46 THEN t = t + 1
        IF (a = 46) AND (t > 1) THEN a = 0    'only DOT after FIRST is cleared
        IF a = 45 AND i>1 THEN a = 0          'so really almost anything do, not just 8
        IF a = 46 AND i = 1 THEN sNum1 = "0" + sNum1
      IF a = 45 OR a = 46 OR a > 47 AND a < 58 THEN sNum1 = sNum1 + CHR(a)
   NEXT
   
   a = ASC(MID(sTxt,1,1))
    IF a = 45 AND MID(sTxt,2,1) = "." THEN sNum1 = "-0" + sNum1
   
   RETURN sNum1

END FUNCTION


'Create a window with an Editbox and a button:
Window_Main = Window_New   (50, 100, 300, 400, "Numeric Entry Filter!")
VAR Label_sTxt = Label_New  (10, 10, 150, 20, "Enter numbers:",, Window_Main)
Edit_1 = EditBox_New       (150, 10, 100, 20, "",ES_RIGHT, Window_Main)
Button_Ok = Button_New     (160, 300, 60, 20, "Ok",, Window_Main)

EditBox_SetText(Edit_1, "")

Screen 12
open cons for output as #1

'Set timer to 300 miliseconds:
SETTIMER(Window_Main, 0, 300, 0 )

DO
   WaitEvent(Window_Main,msg)
   SELECT CASE msg.message
      CASE WM_TIMER
         'Check contents of the edit box every 300 millisecinds
         sTxt = EditBox_GetText(Edit_1)   'get text from edit box
         oldsTxt = sTxt      'make text the oldtext
         sTxt = sNum(sTxt)  'gets new text from function sNum(sTxt) which does the checking
         IF oldsTxt <> sTxt THEN
            EditBox_SetText(Edit_1, sTxt)   'if old text is not the same as the new text then use new text
            pos0 = LEN(sTxt)   'position of character is the length of the current text
            SENDMESSAGE(Edit_1, EM_SETSEL, pos0, pos0)             
         END IF
      CASE WM_LBUTTONDOWN
         IF msg.hwnd = Button_Ok THEN PRINT EditBox_GetText(Edit_1)  'print text to console
         sNumFormat = format(val(sTxt), "######0.###")            
         print sNumFormat
         EditBox_SetText(Edit_1, sNumFormat)
   END SELECT  
   
LOOP UNTIL Window_Event_Close(Window_Main, msg)



END
RNBW
Posts: 267
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Post by RNBW »

I have posted similar code on the Purebasic forum and it has been brought to my notice that numbers such as 123e12, 123e-12 or -123e-12 cannot be entered. I must say it was never my intention to do this, I usually use work arounds. It would be easy enough to allow the entry of e (or E), but a minus in the middle of the entry or two minus signs break the basic rules of the code which prevent either. To get around this will require a lot more thought. I currently don't have time to do this (and my poor brain might not be up to it), so if anyone has any ideas I'd be happy to see them
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Numeric Entry in an EditBox

Post by MrSwiss »

From my viewpoint, the whole issue is a: "non issue", because the EditBox was designed
to enter "Text", not numbers (exclusively) and therefore, is considered: "the wrong tool".

This would have to be custom built, if nothing "like it" is already availlable ...

PS: It's about time, to let this pointless thread die!
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Numeric Entry in an EditBox

Post by jj2007 »

For your inspiration, below a list of valid (and some invalid) number formats that I use to test MovVal:

Code: Select all

1d ...", 0 ; D: trailing d, not h: dec/res4 REAL1
tb4 db "-10101e-1 ...", 0 ; D: trailing e with exponent (no h
tb5 db " ( 1.2345E-123 ) ... brackets OK?", 0 ; D: IsNegNu
tb6 db " -1.23400E-1 ...", 0 ; D: valid/res7 REAL10 -1.23400
tb7 db " -1.2340E-1 ...", 0 ; D: IsNegNum if no expo yet, ne
tb8 db "123.E9 ...", 0 ; D: valid/res9 REAL10 0.0
tb9 db ". (just a dot followed by whitespace...)", 0 ; D: vali
tb10 db "1.2 ...", 0 ; D: valid/res11 REAL10 1.0
tb11 db "1. ...", 0 ; D: valid/res12 REAL10 0.2
tb12 db ".2 ...", 0 ; D: valid/res13 REAL10 -127.0
tb13 db "10101E invalid: trailing e but no exponent", 0 ; inva
tb14 db "just a text (invalid)", 0 ; invalid: not starting wi
tb15 db "( -1.23e-99 ) ... eof bracket?", 0 ; D:/res16 REAL10
tb16 db "-1.23456789e5 ...", 0 ; D:/res17 REAL10 -12345678.9e
tb17 db "-12345678.9e5 ...", 0 ; D:/res18 REAL10 1.234567890e
tb18 db "1.234567890e3 ...", 0/res19 REAL10 123456789.0e3 ; ST
tb19 db "123456789.0e3 ...", 0/res20 REAL10 1234567890.0e3 ;
tb20 db "1234567890e3 ...", 0/res21 REAL10 123.0e3 ; ST(0)=123
tb21 db "123e3 ...", 0/res22 REAL10 12.0
tb22 db "12 ...", 0 ; D: valid/res23 REAL10 21.0
tb23 db "10101b ...", 0 ; B: trailing b/res24 REAL10 21.0
tb24 db "10101y ...", 0 ; B: trailing y/res25 REAL10 65793.0
tb25 db "10101h ...", 0 ; H: trailing h/res26 REAL10 74565.0
tb26 db "$12345 ...", 0 ; H: leading $/res27 REAL10 74565.0
tb27 db "0x12345 ...", 0 ; H: 0x/res28 REAL10 4835.0
tb28 db "12e3h OK for e3_trailing h", 0 ; H: trailing h, e is
tb29 db "123456789012345h ...", 0 ; H: trailing h/res30 REAL1
tb30 db "123",200,"456d abc commas to char200, OK", 0 ; D: wi
tb31 db " (123,456,789,0e3)) abc commas and brackets, bad", 0
tb32 db "$abc45 OK for the $012 format", 0 ; H: leading $/res
tb33 db "0xabc45 OK for the 0x12 format", 0 ; H: 0x/res34 REA
tb34 db "xabc45 no 0 before x", 0 ; H: x without 0, malformed
tb35 db "7fed6fed5fed4fedh OK for a hex qword", 0 ; H: trailin
tb40 db "(0FFFFFFF0h)", 0 ; H: leading $/res41 REAL10 4294967
tb41 db "(0FFFFFFF4h)", 0 ; H: leading $/res44 REAL10 7777.6
tb44 db "7777.666666666666666666 ...", 0 ; DotPos, no expo, l
tb50 db "-1.e-3 ...", 0 ; D: valid/res51 REAL10 0.0002
tb51 db ".2e-3 ...", 0 ; D: valid/res52 REAL10 -0.0002
tb52 db "-.2e-3 ...", 0 ; D: valid/res60 REAL10 -255.0
tb60 db "-0ffh", 0 ; H: valid/res61 REAL10 170.0
tb61 db "10101010Y", 0 ; Y: valid/res62 REAL10 -170.0
tb62 db "-10101010y", 0 ; Y: valid/res70 REAL10 -123.0 ; t5
tb70 db "-123 (preceded by x=)", 0 ; Y: valid/res71 REAL10 -
tb71 db "-123 (preceded by a0)", 0 ; Y: valid/res72 REAL10 -
tb72 db "-123 (preceded by 77)", 0 ; Y: valid/res80 REAL10
tb80 db "12:34:56", 9, "### TIME", 0 ; D: valid - ascii 58/r
tb81 db "9-12-2016", 9, "### DATE, U.S. format", 0 ; D: valid
tb82 db "12, 34, 56", 0 ; D: valid - ascii 44/res83 REAL10 1
tb83 db "12/34/56", 0 ; D: valid - ascii 47/res84 REAL10 77.
tb84 db "77.5% NO, we won't divide by 100, too risky", 0 ; D:
tb85 db "123.4", 9, "567 - and there was a tab before 567", 0
tb86 db '"123.456"', 0, 'quoted "123.456" is ok?', 0 ; D: quot
tb87 db "'123.456'", 0, "quoted '123.456' is ok?", 0 ; D: quot
tb88 db "0", 0, "text after a zero"/res89 REAL10 -127.0
tb89 db "FF - two hex chars without qualifiers $ or 0x or h"/
tb90 db "0xB", 0, "text after a zero"/res91 REAL10 0.0
tb91 db "Chile is not Ch = 12!!", 0/res92 REAL10 12.0
tb92 db "Ch is the number12", 0/res93 REAL10 -127.0
tb93 db " C is a simple C, not valid", 0/res94 REAL10 -127.0
tb94 db "CA is not a valid number without a trailing h or a le
tb95 db "CAh is OK, though", 0/res96 REAL10 0.0
tb96 db "(a) should NOT be a valid number", 0/res97 REAL10 101
tb97 db "1016;1665 - two numbers separated by a semicolon", 0
tb98 db "-.123456789e1", 9, "minus dot", 0
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Numeric Entry in an EditBox

Post by MrSwiss »

jj2007, you can at your option, stick that "ASM mangling" wherever you want ...
Just leave it out of this forum!
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Numeric Entry in an EditBox

Post by jj2007 »

MrSwiss wrote:It's about time, to let this pointless thread die!
My dearest friend Oberlehrerschaumvormmund, can't you mind your own business, please?
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Numeric Entry in an EditBox

Post by MrSwiss »

jj2007 wrote:My dearest friend ...
Won't happen any time soon, anyway.
jj2007 wrote:... can't you mind your own business, please?
You mean, like you always do?

(I'm also capable, of quoting "out of context"!)
RNBW
Posts: 267
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Post by RNBW »

MrSwiss wrote:From my viewpoint, the whole issue is a: "non issue", because the EditBox was designed
to enter "Text", not numbers (exclusively) and therefore, is considered: "the wrong tool".

This would have to be custom built, if nothing "like it" is already availlable ...

PS: It's about time, to let this pointless thread die!
Mr Swiss
From your viewpoint, it may be a non-issue. It is an issue from my point of view and clearly is to the 276 people who have been interested enough to view the thread.

It is useful to what I am developing and you are correct it is text that is being entered. In many instances text is inputted and subsequently converted to a value.

Please do not be dismissive of what others are doing. I would much rather you spent your valuable time with something positive and helpful as you have done many times in the past. If you are not interested in this subject and don't wish to contribute,there is no need to comment. Others may argue with you, but I think these circular arguments are a waste of the forum's space.

I hope you will see the value in not continuing your current vein on this subject and let others who are interested continue to contribute.

By the way, to those who are interested, my code on the Purebasic forum https://www.purebasic.fr/english/viewforum.php?f=12 does in fact allow the entry of numerics such as 123e12 and -123e-12. When I get time I shall try to convert it to Freebasic.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Numeric Entry in an EditBox

Post by jj2007 »

It is actually a nice idea to have an edit box only for numbers; and subclassing an edit control is not rocket science. Sometimes it makes me angry that websites and other GUIs are not able to interpret correctly

+39-333 456 789 (a phone number, obviously)
IT70 P011 2550 3456 0440 0012 345 (an IBAN, obviously)
D30C1661-CDAF-11D0-8A3E-00C04FC9E26E (a GUID, obviously)
... etc ...

Computers should be smarter than human beings, right? Good luck for your project.
RNBW
Posts: 267
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Post by RNBW »

jj2007 wrote:It is actually a nice idea to have an edit box only for numbers; and subclassing an edit control is not rocket science. Sometimes it makes me angry that websites and other GUIs are not able to interpret correctly
Microsoft decided to make it easy to enter numbers into a textbox with ES_NUMBER, but this is for integer numbers only. So it is essential that code routines allow the entry of other types of numbers (which there are many). My routine (which is mainly the work of others) allows simple everyday numbers to be entered. It meets my immediate requirements and my feeling is that it should be made available to other forum users. That's what we are members for, isn't it? To help each other!

I hope that forum members can find a use for it and that they will give examples of its use. I'm getting old in the tooth, but still need lots of help and I am sure beginners will appreciate all the help they can get. I note that this thread currently has 299 views and the Purebasic equivalent has 227 views. This is well over 500 views, so I think there is definitely an interest in the subject.

I shall certainly be using the routine, if I can ever get my project on the way. The biggest problem is that my memory is not as good as it was and by the time I've learned something I've probably forgotten what I've learned. Such is life!

Thank you for showing interest.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Numeric Entry in an EditBox

Post by dodicat »

I don't have "WinGUI.bi"
Maybe go through a temporary file with fprintf and formatted.
On the program end the file can be deleted.
Options for write types and different formats can be sent in parameters.
Trivial example:

Code: Select all

 
#Include "windows.bi"
#include "crt.bi"
#include "file.bi"
'================
dim shared as string tempfile :tempfile="temp.dat"

function save overload(filename as string,num as double ,_format as string="%e",writetype as string="w") as long
dim as string r=writetype
 dim as file ptr fp=fopen(filename,r)
   fprintf(fp,_format,num)
   function=iif(*cast(long ptr,fp),0,-1)
   fclose(fp)
end function

function save overload(filename as string,txt as string ,_format as string="%s",writetype as string="w") as long
dim as string r=writetype
 dim as file ptr fp=fopen(filename,r)
   fprintf(fp,_format,txt)
   function=iif(*cast(long ptr,fp),0,-1)
   fclose(fp)
end function

Function load(file as string) as String
	If FileExists(file)=0 Then Print file;" not found":Sleep:end
   var  f=freefile
    Open file For Binary Access Read As #f
    Dim As String text
    If Lof(f) > 0 Then
      text = String(Lof(f), 0)
      Get #f, , text
    End If
    Close #f
    return text
end Function
'=================

Dim  As MSG msg
Dim  As HWND Main_Win,ClickWin
Main_Win=CreateWindowEx(0,"#32770"," Click",WS_OVERLAPPEDWINDOW Or WS_VISIBLE,200,200,600,500,0,0,0,0)
ClickWin=CreateWindowEx(0,"Button","Click", WS_VISIBLE Or WS_CHILD,0,0,60,30,Main_win,0,0,0)

var EditWindow=CreateWindowEx( WS_EX_CLIENTEDGE,"EDIT","",ws_border or  WS_VISIBLE Or WS_CHILD Or WS_VSCROLL  Or ES_AUTOHSCROLL Or ES_MULTILINE,150,50,200,200,  Main_win,0,0,0)

'freeconsole
While GetMessage( @msg,Main_Win,0,0)
    TranslateMessage(@msg)
    DispatchMessage(@msg)
    Select Case msg.hwnd
    Case Main_Win
        Select Case msg.message
        Case 273  'close by clicking X
            kill tempfile
            End
        End Select
    '-----------------------------     
    Case ClickWin
        Select Case msg.message  
        Case WM_LBUTTONDOWN
            dim as double d=iif(rnd>.5,rnd*.02-rnd*.02,rnd*100000-rnd *100000)
            save(tempfile,d,"%E","a")          'scientific and append
            save(tempfile,chr(13,10),"%s","a") 'string and append for new line
            dim as string l=load(tempfile)
           setWindowText(EditWindow,l )
        End Select
    '------------------------------ 
    End Select'(case main_win)
Wend

  
Post Reply