Numeric Entry in an EditBox

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

Re: Numeric Entry in an EditBox

Postby RNBW » Aug 28, 2018 20:31

That could be useful to limit the characters in a textbox.
RNBW
Posts: 183
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Postby RNBW » Aug 29, 2018 22:50

RNBW wrote:I've had a look at the code and I think I understand what has been done. I can't say that I actually understand what is going on but I can see it. I've put some additional notes in the code to help me in the future (I have the memory span of a gnat!) and I've also incorporated Paul Squires' suggestion, but retained jj2007 equivalent code as a remark. It just shows how many ways there are of doing things.

The revised code follows. I hope it's useful to someone, besides myself. Thank you again for all the help I've been given.

Code: Select all

REM=============================================
'  NUMERIC INPUT IN A TEXTBOX
'  TestSubClass_02.bas
'  This does a check for 0-9 and - or + 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
'  Initial Code by RNBW and subclassing modifications by jj2007
'============================================

#INCLUDE "WinGUI.bi"
#include "string.bi"
#include "crt.bi"

DIM shared AS HWND Window_Main, Button_Ok, Edit_1,Edit_2
DIM shared AS MSG msg
DIM shared AS STRING sTxt
Dim shared as double numb
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
  Dim txtpos as integer
  Dim num3 as double
  Dim txt as string*1000
  wp2=wParam
  if uMsg=WM_CHAR then   ' user typed something
   if wParam <48 or wParam>57 then   ' it's not a number (48="0", 57="9")
      SendMessage(hWnd, WM_GETTEXT, 1000, cast (LPARAM,@txt))    'Paul Squires' suggestion
      'SendMessage(hWnd, WM_GETTEXT, 1000, cast (LONG_PTR,@txt))      ' let's get the current text
      '                                                              text size        ptr to txt
      txtpos=SendMessage(hWnd, EM_GETSEL, 0, 0) and 127   ' and the cursor position
      '                                                                                127 is delete
      if wParam=47 then wp2=0         ' / not allowed
      if wParam=46 and Instr(txt, ".") then wp2=0   ' one dot only
      if (wParam=43 or wParam=45) and txtpos then wp2=0      ' +- only in pos 0
      if wParam<>VK_BACK then         ' wParam <> Backspace
         if wParam<43 or wParam>57 then wp2=0
      endif
   endif
  endif
  CallWindowProc(PrevWinProc, hWnd, uMsg, wp2, lParam)
  if uMsg=WM_CHAR then
         sTxt = EditBox_GetText(Edit_1)
         numb = val(sTxt)
         sTxt = format(numb, "####0.000")
         EditBox_SetText(Edit_2,sTxt)
  endif
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 = CAST(ANY PTR, SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @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)          'not really needed

SetFocus(Edit_1)

DO
   WaitEvent(Window_Main,msg)
LOOP UNTIL Window_Event_Close(Window_Main, msg)
END

I have found that, when editing, it is possible to have both "+" and "-" at the beginning of the numeric entry. Since this is not acceptable, I have amended the code to exclude the "+" because by default the number is positive.

The revised code is below, where it can be seen that I have REMd the old code:

Code: Select all

REM=============================================
'  NUMERIC INPUT IN A TEXTBOX
'  TestSubClass_03.bas
'  This does a check for 0-9 and - or + 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
'  Initial Code by RNBW and subclassing modifications by jj2007
'============================================

#INCLUDE "WinGUI.bi"
#include "string.bi"
#include "crt.bi"

DIM shared AS HWND Window_Main, Button_Ok, Edit_1,Edit_2
DIM shared AS MSG msg
DIM shared AS STRING sTxt
Dim shared as double numb
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
  Dim txtpos as integer
  Dim num3 as double
  Dim txt as string*1000
  wp2=wParam
  if uMsg=WM_CHAR then   ' user typed something
   if wParam <48 or wParam>57 then   ' it's not a number (48="0", 57="9")
      SendMessage(hWnd, WM_GETTEXT, 1000, cast (LPARAM,@txt))    'Paul Squires' suggestion
      'SendMessage(hWnd, WM_GETTEXT, 1000, cast (LONG_PTR,@txt))      ' let's get the current text
      '                                                              text size        ptr to txt
      txtpos=SendMessage(hWnd, EM_GETSEL, 0, 0) and 127   ' and the cursor position
      '                                                                               
      if wParam=47 then wp2=0         ' / not allowed
      if wParam=46 and Instr(txt, ".") then wp2=0   ' one dot only
      REM if (wParam=43 or wParam=45) and txtpos then wp2=0      ' +- only in pos 0
      if wParam=45 and txtpos then wp2=0      ' +- only in pos 0
      if wParam<>VK_BACK then         ' wParam <> Backspace
         REM if wParam<43 or wParam>57 then wp2=0
         if wParam<45 or wParam>57 then wp2=0
      endif
   endif
  endif
  CallWindowProc(PrevWinProc, hWnd, uMsg, wp2, lParam)
  if uMsg=WM_CHAR then
         sTxt = EditBox_GetText(Edit_1)
         numb = val(sTxt)
         sTxt = format(numb, "####0.000")
         EditBox_SetText(Edit_2,sTxt)
  endif
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 = CAST(ANY PTR, SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @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)          'not really needed

SetFocus(Edit_1)

DO
   WaitEvent(Window_Main,msg)
LOOP UNTIL Window_Event_Close(Window_Main, msg)
END
RNBW
Posts: 183
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBoxLothar

Postby RNBW » Aug 29, 2018 23:03

The following is an example of filtered numeric entry into a StringGadget (textbox) using subclassing and FBGUI Library for Windows 2. It is a replica of that for Lothar Schirm's Simple WinAPI Library in the last post.

Code: Select all

'================================
'   NUMERIC INPUT INTO A STRINGGADGET
'   Uses: FBGUI Library for Windows 2
'   NumericInputIntoStringGadget_03.bas
'----------------------------------------------------
'  The input excludes all characters except 0 to 9
'  minus sign and decimal point.
'================================

# Include "window9.bi"
#include "string.bi"
#include "crt.bi"

Dim shared As integer event
DIM shared AS MSG msg
DIM shared AS STRING sTxt  ', oldsTxt
dim shared as double numb 
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
  Dim txtpos as integer
  Dim num3 as double
  Dim txt as string*1000
  wp2=wParam
  if uMsg=WM_CHAR then   ' user typed something
   if wParam <48 or wParam>57 then   ' it's not a number (48="0", 57="9")
      SendMessage(hWnd, WM_GETTEXT, 1000, cast (LPARAM,@txt))    'Paul Squires' suggestion
      'SendMessage(hWnd, WM_GETTEXT, 1000, cast (LONG_PTR,@txt))      ' let's get the current text
      '                                                              text size        ptr to txt
      txtpos=SendMessage(hWnd, EM_GETSEL, 0, 0) and 127   ' and the cursor position
      '                                                                               
      if wParam=47 then wp2=0         ' / not allowed
      if wParam=46 and Instr(txt, ".") then wp2=0   ' one dot only
      if wParam=45 and txtpos then wp2=0      ' - only in pos 0
      if wParam<>VK_BACK then         ' wParam <> Backspace
         if wParam<45 or wParam>57 then wp2=0
      endif
   endif
  endif
  CallWindowProc(PrevWinProc, hWnd, uMsg, wp2, lParam)
  if uMsg=WM_CHAR then
         sTxt = GetGadgetText(3)
         numb = val(sTxt)
         sTxt = format(numb, "####0.000")
         SetGadgetText(4,sTxt)
  endif
End Sub


' Create window and contained gadgets
var main = OpenWindow ("Numeric Input ", 300,10,300,300)
 
var txt1 = TextGadget(1,10,15,100,30,"Input Number:")
TextGadget(2, 10, 60, 100,30, "Formatted Number")

' Set up First StringGadget
var st1 = StringGadget (3,120,10,120,25, "", ES_RIGHT or WS_BORDER)
SetGadgetFont (3, CINT(LoadFont ("arial", 12))) 'Font Gadget

PrevWinProc = CAST(ANY PTR, SetWindowLongPtr(st1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit)))

' Set up Second StringGadget
var st2 = StringGadget (4,120,55,120,25, "", ES_RIGHT or ES_READONLY or WS_BORDER)
SetGadgetFont (4, CINT(LoadFont ("arial", 12))) 'Font Gadget

SetFocus(st1)


Do
 Var ev=WindowEvent
 If ev=EventClose Then End
Loop
jj2007
Posts: 1180
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Numeric Entry in an EditBoxLothar

Postby jj2007 » Aug 29, 2018 23:17

RNBW wrote:The following is an example of filtered numeric entry into a StringGadget (textbox) using subclassing and FBGUI Library for Windows
Glad to see you start liking the subclassing technique ;-)
RNBW
Posts: 183
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBoxLothar

Postby RNBW » Aug 30, 2018 16:13

jj2007 wrote:
RNBW wrote:The following is an example of filtered numeric entry into a StringGadget (textbox) using subclassing and FBGUI Library for Windows
Glad to see you start liking the subclassing technique ;-)

I think it is probably stretching it a bit to say that I like the subclassing technique, because I still don't fully understand it and what I would like to do is to format it to a specific number of decimal points in the Input StringGadget, rather than the Output StringGadget and I've not worked out how to do that yet. But, just to give you a bit of my background, I was a Construction Project Manager for about 40 years and what I found out very early was that there had to be an acceptable solution to a problem. It might not be the one you would prefer to use, but having taken into account the associated risks and costs, if it works use it.

I will try to get a better understanding, but I know it does the job and so I will use it, unless I find something better. So at the moment, in my book you are at the top of the tree!
jj2007
Posts: 1180
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Numeric Entry in an EditBoxLothar

Postby jj2007 » Aug 30, 2018 19:35

RNBW wrote:I will try to get a better understanding
Have a look at the new subclassing thread.
RNBW
Posts: 183
Joined: Apr 11, 2015 11:06
Location: UK

Re: Numeric Entry in an EditBox

Postby RNBW » Oct 07, 2018 10:29

I have posted an example of numeric entry in a grid of textboxes using Lothar Schirm's Simple Windows API Library here https://www.freebasic.net/forum/viewtopic.php?f=8&t=24617&start=45, which followers of this thread may have an interest.

Return to “Tips and Tricks”

Who is online

Users browsing this forum: jj2007 and 6 guests