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
BasicCoder2
Posts: 3906
Joined: Jan 01, 2009 7:03
Location: Australia

Re: Numeric Entry in an EditBox

Post by BasicCoder2 »

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.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Numeric Entry in an EditBox

Post by MrSwiss »

BasicCoder2 wrote:My foray into using the WinGUI.bi file reinforced my conviction that it is easier for me to roll my own GUI controls.
If I where you, I'd stop stressing the "rolling my own", because the reason
for that, is your own inability, to ever write re-usable code ...

Meaning: You would by now, have your own, self written gui-library!
RNBW
Posts: 267
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Post by RNBW »

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.
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.

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
and

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.
Is there any point to the program apart from a programming exercise?
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.

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.
BasicCoder2
Posts: 3906
Joined: Jan 01, 2009 7:03
Location: Australia

Re: Numeric Entry in an EditBox

Post by BasicCoder2 »

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.
Clearly not a satisfactory solution?
Maybe someone can look at the code and find a solution.
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.
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.
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.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Numeric Entry in an EditBox

Post by jj2007 »

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.
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: Numeric Entry in an EditBox

Post by srvaldez »

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)
RNBW
Posts: 267
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Post by RNBW »

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

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
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.
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.
Subclassing is outside Lothar Schirm's library. Lothar has made this sort of thing clear in his postings.

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.
RNBW
Posts: 267
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Post by RNBW »

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.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Numeric Entry in an EditBox

Post by jj2007 »

RNBW wrote:
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.
Subclassing is outside Lothar Schirm's library. Lothar has made this sort of thing clear in his postings.
Doesn't mean it cannot be done:

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)
...
Note this is just a demo showing how you can't type anything above Ascii 57 aka "9". You need to refine it with various checks. I have a source but it's in assembly, sorry.

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
RNBW
Posts: 267
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Post by RNBW »

jj2007 wrote:
RNBW wrote:
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.
Subclassing is outside Lothar Schirm's library. Lothar has made this sort of thing clear in his postings.
Doesn't mean it cannot be done:
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
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Numeric Entry in an EditBox

Post by jj2007 »

RNBW wrote:I get a warning "Passing pointer to scalar, at parameter 3 of SETWINDOWLONGPTR()". I don't know if that has any significance.
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.
Josep Roca
Posts: 564
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: Numeric Entry in an EditBox

Post by Josep Roca »

> 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.
RNBW
Posts: 267
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Post by RNBW »

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.
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.
RNBW
Posts: 267
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Post by RNBW »

RNBW wrote:
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.
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.
I have made some amendments to the code and I seem to have lost any warnings. The way it works now is:

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
RNBW
Posts: 267
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Post by RNBW »

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.

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
Post Reply