Numeric Entry in an EditBox

Post your FreeBASIC tips and tricks here. Please don’t post your code without including an explanation.
BasicCoder2
Posts: 3397
Joined: Jan 01, 2009 7:03

Re: Numeric Entry in an EditBox

Postby BasicCoder2 » Aug 08, 2018 19:48

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: 3222
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Numeric Entry in an EditBox

Postby MrSwiss » Aug 08, 2018 20:22

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

Re: Numeric Entry in an EditBox

Postby RNBW » Aug 08, 2018 21:55

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: 3397
Joined: Jan 01, 2009 7:03

Re: Numeric Entry in an EditBox

Postby BasicCoder2 » Aug 09, 2018 20:59

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

Re: Numeric Entry in an EditBox

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

Re: Numeric Entry in an EditBox

Postby srvaldez » Aug 09, 2018 22:21

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

Re: Numeric Entry in an EditBox

Postby RNBW » Aug 10, 2018 17:11

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

Re: Numeric Entry in an EditBox

Postby RNBW » Aug 11, 2018 15:04

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

Re: Numeric Entry in an EditBox

Postby jj2007 » Aug 11, 2018 16:45

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

Re: Numeric Entry in an EditBox

Postby RNBW » Aug 11, 2018 19:00

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

Re: Numeric Entry in an EditBox

Postby jj2007 » Aug 11, 2018 19:09

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: 441
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: Numeric Entry in an EditBox

Postby Josep Roca » Aug 11, 2018 20:36

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

Re: Numeric Entry in an EditBox

Postby RNBW » Aug 12, 2018 9:59

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

Re: Numeric Entry in an EditBox

Postby RNBW » Aug 24, 2018 15:24

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

Re: Numeric Entry in an EditBox

Postby RNBW » Aug 26, 2018 16:23

I rather like the FBGUI library for windows 2 https://www.freebasic.net/forum/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

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 1 guest