It is currently Mon Nov 19, 2018 4:02 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 17 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Numeric Entry into a EditBox
PostPosted: Wed Jul 11, 2018 3:43 pm 
Offline
User
User

Joined: Thu Jan 02, 2014 5:01 pm
Posts: 54
I have been trawling through the forum for examples of numeric input into a textbox. What I wanted was the following:
Check each character as it is entered to ensure that:

• The character was limited to 0 to 9, minus and decimal point (period)
• Minus can only occur as the first character entered
• There can only be one occurrence of minus
• There can only be one occurrence of a decimal point
• If the first character entered is a decimal point (.123) it will be displayed as 0.123
• If the first character is minus and the second a decimal point (-.123) it will be displayed as -0.123
• The display will be right justified
• It must be editable

I couldn’t find code that did all of these, but was able to find two that came close. I have amalgamated the two. Credit is given in the code to the writers of the original code. I am very grateful to them and I hope that the code below will be useful. I shall be grateful if anyone can improve it or put me right if I have got anything wrong.

Code:
;--------------------------------------------------------------------------------------------
;  Numeric input
;---------------------------------------------------------------------------------------------
;  This is an amalgamation of two programs.  One from Danilo
;  included in RSBasic's WinAPI Library (StringGadget section)
;  and BasicallyPure's program in the Purebasic forum
;  (https://www.purebasic.fr/english/viewtopic.php?f=13&t=50565&hilit=Numeric+entry&start=0)
;  It accepts characters 0 to 9 minus and period.
;  It accepts a minus only as the first character.
;  It only accepts one minus sign and one period in the entry.
;  An entry of .123 displays as 0.123
;  An entry of -.123 is displayed as -0.123
;  The amalgamation of code has been produced by RNBW, who is grateful
;  to all the contributors to the code:
;  Danilo
;  BasicallyPure
;  asked for by 'akee'
;  inspired by 'IdeasVacuum'
;  key assist from 'Shardik'
;---------------------------------------------------------------------------------------------

EnableExplicit

Procedure.s CheckNumeric(iStrGadget.i)
   ;purpose: limit StringGadget to accept only numeric input
   ;with support for floating poing characters: . - + E e
   
   Protected.i iCount, iTextLength, iAccept, iDecimal, iExp, iNeg
   Protected.s sNewText, sChar, sGadgetText
   
   sGadgetText = GetGadgetText(iStrGadget)
   iTextLength = Len(sGadgetText)
   
   For iCount = 1 To iTextLength
     
      sChar = Mid(sGadgetText, iCount, 1)
      iAccept = #False
     
      Select Asc(sChar)
         Case 48 To 57 ; Accepted numbers
            iAccept = #True
            If iExp = 1 : iExp + 1 : EndIf
         Case 43, 45        ; Minus or Plus sign
            If iCount = 1
               iAccept = #True : iNeg = 1
            ElseIf iExp = 1
               iAccept = #True : iExp + 1
            EndIf
         Case 46        ; period
            If Not iDecimal And Not iExp
               iDecimal = #True : iAccept = #True
               If iCount - iNeg = 1 : sChar = "0" + sChar : EndIf
            EndIf
         Case 69, 101 ;    'e' or 'E'
            If Not iExp And iCount > 1 + iNeg
               iExp = 1 : iAccept = #True
            EndIf
      EndSelect
     
      If iAccept : sNewText + sChar : EndIf
     
   Next
   
   SetGadgetText(iStrGadget, sNewText)
   iTextLength = Len(sNewText)
   
   ;windows only
   SendMessage_(GadgetID(iStrGadget),#EM_SETSEL,iTextLength,iTextLength) ;Set cursor to end of string

EndProcedure

If OpenWindow(0,0,0,300,150,"Number of Decimal Places",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  StringGadget(1,10,10,200,20,"",#PB_Text_Right)
  LoadFont (1, "Monaco", 11, #PB_Font_Bold)
  SetGadgetFont(1, FontID(1))
 
  Repeat
    Define EventID=WaitWindowEvent()
    If EventID=#PB_Event_Gadget
      Select EventGadget()
        Case 1
          If EventType() = #PB_EventType_Change
            CheckNumeric(EventGadget())
          EndIf
      EndSelect
    EndIf
    If EventID = #PB_Event_CloseWindow
      End
    EndIf
  ForEver
EndIf


Top
 Profile  
Reply with quote  
 Post subject: Re: Numeric Entry into a EditBox
PostPosted: Thu Jul 12, 2018 7:35 am 
Offline
Addict
Addict
User avatar

Joined: Fri Sep 21, 2007 5:52 am
Posts: 3332
Location: New Zealand
seems to work well, but not "e" exp, needs a bit more thought
as you can type 123.456e1234
the exponent needs to be limited in the range, for float +/- 38 or double +/- 308
so if you have "1." entered you can flag it as a potential of exp and if "e" is entered then range check the numbers after to be
within +/- 38 for float or +/- 308 for double
not sure how to do that right now but will look at it in the morning

_________________
Got winter blues?
Enjoy a Caravan Trip into, "The Land of Grey and Pink", wine and punk weed optional!
https://www.youtube.com/watch?v=9hmFzGTxod4


Top
 Profile  
Reply with quote  
 Post subject: Re: Numeric Entry into a EditBox
PostPosted: Fri Jul 13, 2018 11:39 am 
Offline
User
User

Joined: Thu Jan 02, 2014 5:01 pm
Posts: 54
idle wrote:
seems to work well, but not "e" exp, needs a bit more thought
as you can type 123.456e1234
the exponent needs to be limited in the range, for float +/- 38 or double +/- 308
so if you have "1." entered you can flag it as a potential of exp and if "e" is entered then range check the numbers after to be
within +/- 38 for float or +/- 308 for double
not sure how to do that right now but will look at it in the morning


You are right that the incorporation of the entry of numbers such as 123.456e1234 (or more importantly 123.456e-1234) needs more thought. With what I had in mind, I wouldn't require such numbers to actually be entered.

One of the problems is that the code as written only allows for a minus sign to be the first character entered and only one minus sign is permitted. The e (or E) shouldn't be too much of a problem to change, but you couldn't enter 123e-12 or -123e-12, the first because of the rule I've just mentioned and the latter with a double no-no because it has a minus in the middle of the entry and also two minus signs.

These problems have to be overcome and it's not easy. I must say, if I was going to need to enter a 123e-12 type number, I would probably use a completely different method, such as entering the whole number and then carrying out a check on its validity, or alternatively enter a number without the e-12 part and identify that with a label after the textbox and deal with the number itself in code outside the entry. Personnally, I would favour the latter method. It's much easier to deal with.

I currently don't have time to look into it, but if anyone could come up with solutions I would like to see them.

Personnally, my next step is to produce a grid of textboxes with numeric entry into them. If anyone has any ideas, it would save my poor old brain a few headaches!


Top
 Profile  
Reply with quote  
 Post subject: Re: Numeric Entry into a EditBox
PostPosted: Fri Jul 13, 2018 1:30 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Oct 06, 2006 3:57 pm
Posts: 482
Location: England
RNBW wrote:
idle wrote:
Personnally, my next step is to produce a grid of textboxes with numeric entry into them. If anyone has any ideas, it would save my poor old brain a few headaches!


I use a scroll areagadget and an list (array) of stringgadgets for my entrirley PB based grid gadget - but it's a bit of a bodge :)


Top
 Profile  
Reply with quote  
 Post subject: Re: Numeric Entry into a EditBox
PostPosted: Fri Jul 13, 2018 2:19 pm 
Offline
User
User

Joined: Thu Jan 02, 2014 5:01 pm
Posts: 54
I must be going daft (ask my wife she'll probably confirm that - she's being saying it for years). The code DOES allow the input of numbers such as 123e24 and -123e-24. I found I was checking it out using old code, which didn't allow it because I had stripped out the incorporation of 'e'. I decided to include it before I posted the code.


Top
 Profile  
Reply with quote  
 Post subject: Re: Numeric Entry into a EditBox
PostPosted: Fri Jul 13, 2018 5:09 pm 
Offline
User
User

Joined: Thu Jan 02, 2014 5:01 pm
Posts: 54
captain_skank wrote:
RNBW wrote:
idle wrote:
Personnally, my next step is to produce a grid of textboxes with numeric entry into them. If anyone has any ideas, it would save my poor old brain a few headaches!


I use a scroll areagadget and an list (array) of stringgadgets for my entrirley PB based grid gadget - but it's a bit of a bodge :)


Is your grid gadget on the forum?


Top
 Profile  
Reply with quote  
 Post subject: Re: Numeric Entry into a EditBox
PostPosted: Thu Jul 19, 2018 9:31 am 
Offline
User
User

Joined: Thu Jan 02, 2014 5:01 pm
Posts: 54
Code:
;windows only
   SendMessage_(GadgetID(iStrGadget),#EM_SETSEL,iTextLength,iTextLength) ;Set cursor to end of string

Is there an equivalent Mac OS equivalent to #EM_SETSEL, or is there another way of achieving the same result?


Top
 Profile  
Reply with quote  
 Post subject: Re: Numeric Entry into a EditBox
PostPosted: Sat Aug 11, 2018 3:39 pm 
Offline
User
User

Joined: Thu Jan 02, 2014 5:01 pm
Posts: 54
Unfortunately, the code does not work if you try to edit the entered number if a single character precedes the decimal point, such as 1.234 or 0.234

I've tried to resolve this, but unsuccessfully. Can anyone help?


Top
 Profile  
Reply with quote  
 Post subject: Re: Numeric Entry into a EditBox
PostPosted: Sat Aug 11, 2018 4:03 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 1569
Location: Germany
RNBW wrote:
Code:
;windows only
   SendMessage_(GadgetID(iStrGadget),#EM_SETSEL,iTextLength,iTextLength) ;Set cursor to end of string

Is there an equivalent Mac OS equivalent to #EM_SETSEL, or is there another way of achieving the same result?

You may take a look into this cross-platform example which allows to get and set the cursor position in a StringGadget. To position the cursor at the end you should change
Code:
SetCursorPosition(0, 16) ; Set cursor in front of 'fox'
to
Code:
SetCursorPosition(0, Len(GetGadgetText(0)))


Top
 Profile  
Reply with quote  
 Post subject: Re: Numeric Entry into a EditBox
PostPosted: Sun Aug 12, 2018 1:52 am 
Offline
Addict
Addict

Joined: Mon Feb 16, 2015 2:49 pm
Posts: 1610
RNBW wrote:
The character was limited to 0 to 9, minus and decimal point (period)

You can't hard-check for a decimal point (period) as different countries use different decimal separators - some use a comma, for example. So you need to get the locale setting for the decimal separator at runtime, and check for that in your text input routine (not for a period).


Top
 Profile  
Reply with quote  
 Post subject: Re: Numeric Entry into a EditBox
PostPosted: Mon Aug 13, 2018 11:42 am 
Offline
User
User

Joined: Thu Jan 02, 2014 5:01 pm
Posts: 54
Dude wrote:
RNBW wrote:
The character was limited to 0 to 9, minus and decimal point (period)

You can't hard-check for a decimal point (period) as different countries use different decimal separators - some use a comma, for example. So you need to get the locale setting for the decimal separator at runtime, and check for that in your text input routine (not for a period).


What I have in mind to ultimately use the code for will be British only, so a check for a decimal point is OK. However, I do take your point that for a universal solution a check should also be made for a comma. I should say, though, that this can lead to all sorts of formatting arguments and solutions (how thousands are divided and so on), so the code will be quite long and complex and, I would suggest, not for the simple numeric entry into an EditBox that I am looking at.

Some of the separation of thousands 1,234,567 1 234 567 1'234'567 and that's not taking into account how the decimal point is dealt with.

Of course, there are also the arguments about the types of numbers that should be entered, and there are many of these. Maybe I should have headed the thread "Simple Numeric Entry into an EditBox".


Top
 Profile  
Reply with quote  
 Post subject: Re: Numeric Entry into a EditBox
PostPosted: Mon Aug 13, 2018 11:46 am 
Offline
User
User

Joined: Thu Jan 02, 2014 5:01 pm
Posts: 54
Shardik wrote:
You may take a look into this cross-platform example which allows to get and set the cursor position in a StringGadget. To position the cursor at the end you should change
Code:
SetCursorPosition(0, 16) ; Set cursor in front of 'fox'
to
Code:
SetCursorPosition(0, Len(GetGadgetText(0)))


Thank you. I'll have a look at the code.


Top
 Profile  
Reply with quote  
 Post subject: Re: Numeric Entry into a EditBox
PostPosted: Mon Aug 27, 2018 5:03 pm 
Offline
User
User

Joined: Thu Jan 02, 2014 5:01 pm
Posts: 54
RNBW wrote:
Unfortunately, the code does not work if you try to edit the entered number if a single character precedes the decimal point, such as 1.234 or 0.234

I've tried to resolve this, but unsuccessfully. Can anyone help?


The only way that I can see to get over this is to remove or REM the line
Code:
 If iCount - iNeg = 1 : sChar = "0" + sChar : EndIf


The user can then enter 0.123 -0.123 .123 or -.123 depending on preference. It is then possible to format the number after input. I'll have a look at this.

Shardick
I must say I like the solution you gave for setting the cursor position. Your page
Quote:
https://www.purebasic.fr/english/viewtopic.php?f=19&t=43583&start=11
is very useful.


Top
 Profile  
Reply with quote  
 Post subject: Re: Numeric Entry into a EditBox
PostPosted: Mon Oct 22, 2018 11:26 am 
Offline
User
User

Joined: Thu Jan 02, 2014 5:01 pm
Posts: 54
Time flies. I meant to look at this straight away after my last post.

At the moment, there are two problems that I have with the code that I originally posted.

1. Whenever you edit the number, the cursor then flies to after the last digit, and
2. If you try to edit a single number before the decimal point, it can only be done by entering a character before the first character and then deleting the character after the inserted character.

I suspect that (2) might be resolved by a solution to (1).

Does anyone know how you can insert a character and the cursor remain at the inserted character, rather than flying to after the last digit?


Top
 Profile  
Reply with quote  
 Post subject: Re: Numeric Entry into a EditBox
PostPosted: Wed Oct 24, 2018 11:01 am 
Offline
User
User

Joined: Thu Jan 02, 2014 5:01 pm
Posts: 54
RNBW wrote:
Time flies. I meant to look at this straight away after my last post.

At the moment, there are two problems that I have with the code that I originally posted.

1. Whenever you edit the number, the cursor then flies to after the last digit, and
2. If you try to edit a single number before the decimal point, it can only be done by entering a character before the first character and then deleting the character after the inserted character.

I suspect that (2) might be resolved by a solution to (1).

Does anyone know how you can insert a character and the cursor remain at the inserted character, rather than flying to after the last digit?


Well 75 views at my last post, but no suggestions how to get over the problem. I was hoping that someone would come up with perhaps a sub-classing solution (which has been done on other forums). I have to admit not being able to fully get my head around sub-classing. I have tried but unsuccessfully.

So not to be detered, I looked for a completely different solution. I had previously scoured the Purebasic forums (English and German) and looked back at some of the solutions I found. I came up with the code below, which I modified a bit. It gives me what I want in respect of editing, i.e. leaving the cursor at the point of edit rather than jumping to the end each time. I would be pleased to see any suggestions for improvements.

Code:
;-------------------------------------------------------------------------
;  Filename:  NumericInput_04.pb
;
;  From original code by Danilo and ts-soft
;  http://www.purebasic.fr/german/viewtopic.php?p=299222#p299222
;
;  Modifications by RNBW 22 October 2018
;
;  Input numeric values in the range "-", ".", "0 to 9"
;  into a StringGadget
;  The number is entered into the first box and this is then
;  displayed in the second box as a number formatted to
;  3 decimal places.  The number of decimal places can be
;  changed by changing the value of dec in the program.
;  If you want thousand commas in the displayed number,
;  comment out "formNum = StrD(numb, dec)" and
;  remove the comment to
;  "formNum = FormatNumber(numb,dec)"
;-------------------------------------------------------------------------

EnableExplicit

Global formNum.s
Global numb.d
Global dec.i

Procedure checkFloatInput(gadget)
    Protected start.i, count.i, pointcount.i, new.s
    SendMessage_(GadgetID(gadget), #EM_GETSEL, @start, 0)
    Protected txt$ = GetGadgetText(gadget)
    Protected *p.Character = @txt$
   
    While *p\c ; <> 0
        If *p\c = '.'
            pointcount + 1
            If pointcount < 2
                new + Chr(*p\c)
            Else
                If start > count : start - 1 : EndIf
            EndIf
        ElseIf count = 0 And *p\c = '-'
           new + Chr('-')
        ElseIf *p\c >= '0' And *p\c <= '9'
            new + Chr(*p\c)
        Else
            start - 1
        EndIf
        *p + SizeOf(Character)
        count + 1
    Wend
    SetGadgetText(gadget, new)
    SendMessage_(GadgetID(gadget), #EM_SETSEL, start, start)
EndProcedure

Define event
If OpenWindow(0, 0, 0, 300, 150, "Numeric Input Into A StringGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   
   If LoadFont(1, "Arial", 10)
      SetGadgetFont(#PB_Default, FontID(1))   ; Set the loaded Arial 10 font as new standard
   EndIf
   TextGadget(0, 10, 20, 200, 20, "Enter Number in box below")
   TextGadget(3, 10, 85, 200, 20, "Display formatted number")
   
   If LoadFont(2,"Arial",11, #PB_Font_Bold)
      SetGadgetFont(#PB_Default, FontID(2))   ; Set the loaded Arial 15 font as new standard
   EndIf
   StringGadget(1, 10,  50, 100, 25, "", #ES_RIGHT)
   StringGadget(2, 10, 110, 100, 25, "", #ES_RIGHT | #ES_READONLY)  ; this gadget is read-only
   
    SetActiveGadget(1)      ; set focus in StringGadget(1)

    Repeat
        event = WaitWindowEvent()
        If event = #PB_Event_CloseWindow : End
        ElseIf event = #PB_Event_Gadget
            ;If EventGadget()  = 1 Or EventGadget() = 2  ; this line is not actually required
                If EventType() = #PB_EventType_Change
                   checkFloatInput(EventGadget())
                   numb = ValD(GetGadgetText(1))
                   dec = 3    ; set number of decimal places
                   
                   formNum = StrD(numb, dec)
                   ;formNum = FormatNumber(numb,dec)   ; this would place commas in the displayed number
                   SetGadgetText(2, formNum)
                EndIf
            ;EndIf
        EndIf
    ForEver
EndIf


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 17 posts ]  Go to page 1, 2  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye