Numeric Entry in an EditBox
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Re: Numeric Entry in an EditBox
When you click the mouse just before the decimal point with a number in it such as 3.000, to say change it to 4.000, and then back space the cursor to erase the 3 the cursor jumps to the end of the number.
One thing that is important if a program is to be of use to others is consistent and expected behaviours by the controls.
Is there any point to the program apart from a programming exercise?
My foray into using the WinGUI.bi file reinforced my conviction that it is easier for me to roll my own GUI controls. Should I need anything better I would want a GUI Designer such as the one I last used over a decade ago, Visual Basic.
One thing that is important if a program is to be of use to others is consistent and expected behaviours by the controls.
Is there any point to the program apart from a programming exercise?
My foray into using the WinGUI.bi file reinforced my conviction that it is easier for me to roll my own GUI controls. Should I need anything better I would want a GUI Designer such as the one I last used over a decade ago, Visual Basic.
Re: Numeric Entry in an EditBox
If I where you, I'd stop stressing the "rolling my own", because the reasonBasicCoder2 wrote:My foray into using the WinGUI.bi file reinforced my conviction that it is easier for me to roll my own GUI controls.
for that, is your own inability, to ever write re-usable code ...
Meaning: You would by now, have your own, self written gui-library!
Re: Numeric Entry in an EditBox
It is caused by the EM_SETSEL message and the line of code that places a 0 before the decimal point if the number starts with a decimal point or a negative number or there is a single number before the decimal point. Removing the character before the decimal point changes the number to start with a zero. For example, 4.000: if the 4 is deleted, the number becomes 0.000 and the caret moves to the end of the number. It only happens when trying to make changes before the decimal point when there is only one character before the decimal point.BasicCoder2 wrote:When you click the mouse just before the decimal point with a number in it such as 3.000, to say change it to 4.000, and then back space the cursor to erase the 3 the cursor jumps to the end of the number.
One thing that is important if a program is to be of use to others is consistent and expected behaviours by the controls.
Is there any point to the program apart from a programming exercise?
My foray into using the WinGUI.bi file reinforced my conviction that it is easier for me to roll my own GUI controls. Should I need anything better I would want a GUI Designer such as the one I last used over a decade ago, Visual Basic.
Not perfect, but the work around is as follows:
Change 4.000 to 1.000: Move caret before the 4 enter 1 and delete 4. This will give the required change to 1.000.
Maybe someone can look at the code and find a solution. I have not been able to without REMing the line
Code: Select all
IF a = 46 AND i = 1 THEN sNum1 = "0" + sNum1
Code: Select all
IF a = 45 AND MID(sTxt,2,1) = "." THEN sNum1 = "-0" + sNum1
Removing these lines will not automatically place a 0 before a number starting with a decimal point. However, the user can type a 0 (.234 type as 0.234 or -.123 type as -0.123 or -). If the number is left as .123 this is solved after clicking calculate with the final formatting of the displayed numbers.
I will leave it to the user to decide how he (or she) goes about it. Leave as is, or REM or remove the two offending lines.
Yes. It is a smaller exercise carried out to sort out problems before I use it as the basis of something more complicated. I very rarely do anything without there being a reason for doing it. I always start off with something simple and then progress to the more complicated.Is there any point to the program apart from a programming exercise?
Now that I have got this working with Lothar's library, I shall try it out with other libraries before deciding finally which I want to use.
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Re: Numeric Entry in an EditBox
Clearly not a satisfactory solution?RNBW wrote:Not perfect, but the work around is as follows:
Change 4.000 to 1.000: Move caret before the 4 enter 1 and delete 4. This will give the required change to 1.000.
An ideal solution would be to change the code that reads the keyboard but that is hidden in the GUI library. With my own edit textbox routine you edit a string version of whatever data type is being used and on hitting the Enter key the entry is converted to the appropriate format. Each text box has a data type property.Maybe someone can look at the code and find a solution.
Using a popular GUI library would have the advantage of making the code easily readable by others who use the same library and thus easier to offer solutions or exchange ideas.Now that I have got this working with Lothar's library, I shall try it out with other libraries before deciding finally which I want to use.
Re: Numeric Entry in an EditBox
The best and most straightforward solution (at least for Windows) is to subclass the edit control, and to intercept keyboard messages before they get displayed in the box. See Numbers only for a working example.
Re: Numeric Entry in an EditBox
here's a calculator example using FBGUI library for windows 2 viewtopic.php?p=160004#p160004
it's a different library but perhaps you could adapt the code, the example adds keyboard shortcuts, for example AddKeyboardShortcut(hwnd,0,VK_NUMPAD9,KEYPAD_9)
it's a different library but perhaps you could adapt the code, the example adds keyboard shortcuts, for example AddKeyboardShortcut(hwnd,0,VK_NUMPAD9,KEYPAD_9)
Re: Numeric Entry in an EditBox
This example is for single textbox.
I have changed the EM_SETSEL message and this results, where there is a single character before the decimal point and it is deleted, in the character being deleted and replaced with a highlighted 0 which is then overwritten by your change
1.234 --> move caret to right of the 1 --> delete the 1 --> a zero appears in place of the 1 highlighted in blue --> overtype with new character say 2.234.
If you don't like this then REM out the two lines described in an earlier post:
I am posting the code for both versions:
Method 1: Maintaining the 0.123 and -0.123 entry. Output 0.123 and -0.123
DELETED: SORRY THIS DOESN'T WORK WHEN ENTERING .123 or -.123
Method 2: Entry will be .123 or -.123: Output 0.123 or -0.123
What should be remembered is that I am programming this for a purpose. Anyone using my final code will only enter numbers like 1.234 or 0.275 or 20.005. I am satisfied with either of the above for my own use, but I am open to other solutions. But remember that what I am looking for is entry into a textbox where each character is checked that it is in the range (0 to 9 or - or .). I know some will disagree with the method and there are many other solutions using other methods, but this is the one I wish to use.
I may now look at other libraries and see if I can get the routines to work in them. This may be of more use to those using more common libraries.
I have changed the EM_SETSEL message and this results, where there is a single character before the decimal point and it is deleted, in the character being deleted and replaced with a highlighted 0 which is then overwritten by your change
1.234 --> move caret to right of the 1 --> delete the 1 --> a zero appears in place of the 1 highlighted in blue --> overtype with new character say 2.234.
If you don't like this then REM out the two lines described in an earlier post:
I am posting the code for both versions:
Method 1: Maintaining the 0.123 and -0.123 entry. Output 0.123 and -0.123
DELETED: SORRY THIS DOESN'T WORK WHEN ENTERING .123 or -.123
Method 2: Entry will be .123 or -.123: Output 0.123 or -0.123
Code: Select all
REM=============================================
' NUMERIC INPUT IN A TEXTBOX
' NumericInputInTextBox_03.bas
' 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.
' Characters entered are right justified
' Code by RNBW.
'============================================
#INCLUDE "WinGUI.bi"
#include "string.bi"
DIM shared AS HWND Window_Main, Button_Ok, Edit_1,Edit_2
DIM shared AS MSG msg
DIM shared AS STRING sTxt, oldsTxt
DIM shared AS INTEGER pos0
dim shared as double numb
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, 200, "Numeric Entry Filter!")
VAR Label_sTxt = Label_New (10, 10, 150, 20, "Enter numbers:",, Window_Main)
Var label_2 = Label_New (10, 40, 150, 20, "Number to 3 dec",, Window_Main)
Edit_1 = EditBox_New (150, 10, 100, 20, "",ES_RIGHT or WS_BORDER, Window_Main)
Edit_2 = EditBox_New (150, 40, 100, 20, "",ES_RIGHT or ES_READONLY or WS_BORDER, Window_Main)
Button_Ok = Button_New (160, 100, 60, 20, "Ok",, Window_Main)
'Set timer to 300 miliseconds:
SETTIMER(Window_Main, 0, 100, 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
sTxt = EditBox_GetText(Edit_1)
numb = val(sTxt)
sTxt = format(numb, "####0.000")
EditBox_SetText(Edit_2,sTxt)
END SELECT
LOOP UNTIL Window_Event_Close(Window_Main, msg)
END
Subclassing is outside Lothar Schirm's library. Lothar has made this sort of thing clear in his postings.Postby jj2007 » Aug 09, 2018 21:26
The best and most straightforward solution (at least for Windows) is to subclass the edit control, and to intercept keyboard messages before they get displayed in the box. See Numbers only for a working example.
I may now look at other libraries and see if I can get the routines to work in them. This may be of more use to those using more common libraries.
Re: Numeric Entry in an EditBox
Please note that I have deleted the code that allows editing of numbers with one digit before the decimal point. Regrettably, it just doesn't work. That particular code would be my preferred option, but unfortunately, I just can't get it to work. It works for all other editing, but not if there is just a single digit before the decimal point.
I'd appreciate help on this matter.
I'd appreciate help on this matter.
Re: Numeric Entry in an EditBox
Doesn't mean it cannot be done:RNBW wrote:Subclassing is outside Lothar Schirm's library. Lothar has made this sort of thing clear in his postings.Postby jj2007 » Aug 09, 2018 21:26
The best and most straightforward solution (at least for Windows) is to subclass the edit control, and to intercept keyboard messages before they get displayed in the box. See Numbers only for a working example.
Code: Select all
Dim shared as any ptr PrevWinProc
...
Sub SubEdit(ByVal hWnd As HWND, ByVal uMsg As UINT, ByVal wParam As WPARAM, ByVal lParam As LPARAM)
Dim as WPARAM wp2
wp2=wParam
if uMsg=WM_CHAR then
print wParam; " ";
if wParam>57 then wp2=0: print wParam;"? "; ' *** BUILD as console to see these ***
endif
CallWindowProc(PrevWinProc, hWnd, uMsg, wp2, lParam)
End Sub
'Create a window with an Editbox and a button:
Window_Main = Window_New (50, 100, 300, 200, "Numeric Entry Filter!")
VAR Label_sTxt = Label_New (10, 10, 150, 20, "Enter numbers:",, Window_Main)
Var label_2 = Label_New (10, 40, 150, 20, "Number to 3 dec",, Window_Main)
Edit_1 = EditBox_New (150, 10, 100, 20, "",ES_RIGHT or WS_BORDER, Window_Main)
PrevWinProc=SetWindowLongPtr(Edit_1, GWLP_WNDPROC, @SubEdit)
...
Full FB code (for the purpose of testing, WM_TIMER+999 disactivates your checks):
Code: Select all
REM=============================================
' NUMERIC INPUT IN A TEXTBOX
' NumericInputInTextBox_03.bas
' 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.
' Characters entered are right justified
' Code by RNBW.
'============================================
#INCLUDE "WinGUI.bi"
#include "string.bi"
DIM shared AS HWND Window_Main, Button_Ok, Edit_1,Edit_2
DIM shared AS MSG msg
DIM shared AS STRING sTxt, oldsTxt
DIM shared AS INTEGER pos0
dim shared as double numb
Dim shared as any ptr PrevWinProc
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
Sub SubEdit(ByVal hWnd As HWND, ByVal uMsg As UINT, ByVal wParam As WPARAM, ByVal lParam As LPARAM)
Dim as WPARAM wp2
wp2=wParam
if uMsg=WM_CHAR then
print wParam; " ";
if wParam>57 then wp2=0: print wParam;"? ";
endif
CallWindowProc(PrevWinProc, hWnd, uMsg, wp2, lParam)
End Sub
'Create a window with an Editbox and a button:
Window_Main = Window_New (50, 100, 300, 200, "Numeric Entry Filter!")
VAR Label_sTxt = Label_New (10, 10, 150, 20, "Enter numbers:",, Window_Main)
Var label_2 = Label_New (10, 40, 150, 20, "Number to 3 dec",, Window_Main)
Edit_1 = EditBox_New (150, 10, 100, 20, "",ES_RIGHT or WS_BORDER, Window_Main)
PrevWinProc=SetWindowLongPtr(Edit_1, GWLP_WNDPROC, @SubEdit)
Edit_2 = EditBox_New (150, 40, 100, 20, "",ES_RIGHT or ES_READONLY or WS_BORDER, Window_Main)
Button_Ok = Button_New (160, 100, 60, 20, "Ok",, Window_Main)
'Set timer to 300 miliseconds:
SETTIMER(Window_Main, 0, 100, 0 )
DO
WaitEvent(Window_Main,msg)
SELECT CASE msg.message
CASE WM_TIMER+999
'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
sTxt = EditBox_GetText(Edit_1)
numb = val(sTxt)
sTxt = format(numb, "####0.000")
EditBox_SetText(Edit_2,sTxt)
END SELECT
LOOP UNTIL Window_Event_Close(Window_Main, msg)
END
Re: Numeric Entry in an EditBox
Thanks for your response. I'm not too clear about your code. You'll have to leave it with me whilst I try to get my head around it. By the way I get a warning "Passing pointer to scalar, at parameter 3 of SETWINDOWLONGPTR()". I don't know if that has any significance.jj2007 wrote:Doesn't mean it cannot be done:RNBW wrote:Subclassing is outside Lothar Schirm's library. Lothar has made this sort of thing clear in his postings.Postby jj2007 » Aug 09, 2018 21:26
The best and most straightforward solution (at least for Windows) is to subclass the edit control, and to intercept keyboard messages before they get displayed in the box. See Numbers only for a working example.
Re: Numeric Entry in an EditBox
The last para of SetWindowLongPtr is definitely a pointer - to the WndProc. Looks like a FB bug. In any case, it works, and you can ignore the warning.RNBW wrote:I get a warning "Passing pointer to scalar, at parameter 3 of SETWINDOWLONGPTR()". I don't know if that has any significance.
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: Numeric Entry in an EditBox
> The last para of SetWindowLongPtr is definitely a pointer - to the WndProc. Looks like a FB bug. In any case, it works, and you can ignore the warning.
It is not a FB bug. In the declare, it is defined as a LONG (32-bit) or LONG_PTR (64-bit), that is an scalar. Therefore, if you want to pass a pointer you have to cast it: SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit)). Using LONG_PTR will work both with 32 and 64 bit because LONG_PTR evaluates as a LONG when compiled with 32-bit.
It is not a FB bug. In the declare, it is defined as a LONG (32-bit) or LONG_PTR (64-bit), that is an scalar. Therefore, if you want to pass a pointer you have to cast it: SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit)). Using LONG_PTR will work both with 32 and 64 bit because LONG_PTR evaluates as a LONG when compiled with 32-bit.
Re: Numeric Entry in an EditBox
I've changed the code and it works as you say but, I am still left with a warning on the same line (63) of "warning 4(1): Suspicious pointer assignment. It does, however, compile and work OK.Josep Roca wrote:> The last para of SetWindowLongPtr is definitely a pointer - to the WndProc. Looks like a FB bug. In any case, it works, and you can ignore the warning.
It is not a FB bug. In the declare, it is defined as a LONG (32-bit) or LONG_PTR (64-bit), that is an scalar. Therefore, if you want to pass a pointer you have to cast it: SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit)). Using LONG_PTR will work both with 32 and 64 bit because LONG_PTR evaluates as a LONG when compiled with 32-bit.
Re: Numeric Entry in an EditBox
I have made some amendments to the code and I seem to have lost any warnings. The way it works now is:RNBW wrote:I've changed the code and it works as you say but, I am still left with a warning on the same line (63) of "warning 4(1): Suspicious pointer assignment. It does, however, compile and work OK.Josep Roca wrote:> The last para of SetWindowLongPtr is definitely a pointer - to the WndProc. Looks like a FB bug. In any case, it works, and you can ignore the warning.
It is not a FB bug. In the declare, it is defined as a LONG (32-bit) or LONG_PTR (64-bit), that is an scalar. Therefore, if you want to pass a pointer you have to cast it: SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit)). Using LONG_PTR will work both with 32 and 64 bit because LONG_PTR evaluates as a LONG when compiled with 32-bit.
1.. Enter the number in the Textbox
2.. Press the FORMAT button
3.. The number is formatted to 3 decimal places.
4.. The number can now be edited.
5.. Pressing FORMAT after editing will format the number to 3 decimal places.
The number of decimal places is easily changed in the code in the "CASE WM_LBUTTONDOWN" section in the line "sTxt = format(numb, "####0.000")".
Any comments on further improvements will be appreciated.
Code: Select all
'=============================================
' NUMERIC INPUT IN A TEXTBOX
' NumericInputInTextBox_02C.bas
' 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.
' Pressing the FORMAT button formats the number to 3 decimal places
'============================================
#INCLUDE "WinGUI.bi"
#INCLUDE "string.bi"
DIM SHARED AS HWND Window_Main, Button_Format, Edit_1
DIM SHARED AS MSG msg
DIM SHARED AS STRING sTxt, oldsTxt
DIM SHARED AS INTEGER pos0
DIM SHARED AS DOUBLE numb
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 = 45 OR a = 46 OR a > 47 AND a < 58 THEN sNum1 = sNum1 + CHR(a)
NEXT
RETURN sNum1
END FUNCTION
'Create a window with an Editbox and a button:
Window_Main = Window_New(50, 100, 300, 200, "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 OR WS_BORDER, Window_Main)
Button_Format = Button_New(160, 100, 60, 20, "Format",, Window_Main)
'Set timer to 300 miliseconds:
SETTIMER(Window_Main, 0, 100, 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_Format THEN
' Format the number in the cell
sTxt = EditBox_GetText(Edit_1)
numb = val(sTxt)
sTxt = format(numb, "####0.000")
EditBox_SetText(Edit_1,sTxt)
END IF
END SELECT
LOOP UNTIL Window_Event_Close(Window_Main, msg)
END
Re: Numeric Entry in an EditBox
I rather like the FBGUI library for windows 2 viewtopic.php?f=14&t=17058. It is very much like Purebasic of which I am also a fan.
This is my first attempt at adapting the code for Lothar Schirm's library to FBGUI for windows 2.
The thing I don't like about it, is that when an inadmissable character is entered the cursor returns to the beginning of the entry. I would rather it stayed where it was, or moved to the end, but I don't know how to achieve this.
This is my first attempt at adapting the code for Lothar Schirm's library to FBGUI for windows 2.
The thing I don't like about it, is that when an inadmissable character is entered the cursor returns to the beginning of the entry. I would rather it stayed where it was, or moved to the end, but I don't know how to achieve this.
Code: Select all
'=================================
' NUMERIC INPUT INTO A STRINGGADGET
' NumericInputIntoStringGadget_02.bas
'-----------------------------------------------------
' The input excludes all characters except 0 to 9
' minus sign and decimal point.
' Currently, if an inadmissable character is
' entered, the cursor returns to the front of the
' number. I would rather it remained in the
' position at which it was tried to enter an
' inadmissable number.
'=================================
# Include "window9.bi"
#include "string.bi"
Dim As integer event
dim shared as hwnd hwnd
'dim as integer hwnd
'DIM shared AS HWND Window_Main, Button_Ok, Edit_1,Edit_2
DIM shared AS MSG msg
DIM shared AS STRING sTxt, oldsTxt
DIM shared AS INTEGER pos0
dim shared as double numb
'Function to check that character input is 0-9, - or .
FUNCTION sNum(BYVAL sTxt AS STRING) AS STRING
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 = 45 OR a = 46 OR a > 47 AND a < 58 THEN sNum1 = sNum1 + CHR(a)
NEXT
RETURN sNum1
END FUNCTION
' Create window and contained gadgets
hwnd = OpenWindow ("Numeric Input ", 300,10,300,300)
TextGadget(1,10,15,100,30,"Input Number:")
StringGadget (2,120,10,120,25, "", ES_RIGHT or WS_BORDER)
SetGadgetFont (2, CINT(LoadFont ("arial", 12))) 'Font Gadget
ButtonGadget(3,20,60,100,20, "Format")
Do
event = WaitEvent ()
If event = eventclose Then End
If event = eventgadget Then
SELECT CASE eventnumber
CASE 2
sTxt = GetGadgetText(2)
oldsTxt = sTxt 'make text the oldtext
sTxt = sNum(sTxt) 'gets new text from function sNum(sTxt) which does the checking
IF oldsTxt <> sTxt THEN
SetGadgetText(2, sTxt)
'SENDMESSAGE(2, EM_SETSEL, pos0, pos0)
END IF
Case 3
sTxt = GetGadgetText(2)
numb = val(sTxt)
sTxt = format(numb, "####0.000")
SetGadgetText(2, sTxt)
END SELECT
end if
Loop