Numeric Entry in an EditBox
Re: Numeric Entry in an EditBox
That could be useful to limit the characters in a textbox.
Re: Numeric Entry in an EditBox
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.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
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
Re: Numeric Entry in an EditBoxLothar
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
Re: Numeric Entry in an EditBoxLothar
Glad to see you start liking the subclassing technique ;-)RNBW wrote:The following is an example of filtered numeric entry into a StringGadget (textbox) using subclassing and FBGUI Library for Windows
Re: Numeric Entry in an EditBoxLothar
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.jj2007 wrote:Glad to see you start liking the subclassing technique ;-)RNBW wrote:The following is an example of filtered numeric entry into a StringGadget (textbox) using subclassing and FBGUI Library for Windows
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!
Re: Numeric Entry in an EditBoxLothar
Have a look at the new subclassing thread.RNBW wrote:I will try to get a better understanding
Re: Numeric Entry in an EditBox
I have posted an example of numeric entry in a grid of textboxes using Lothar Schirm's Simple Windows API Library here viewtopic.php?f=8&t=24617&start=45, which followers of this thread may have an interest.
Re: Numeric Entry in an EditBox
It's some time since I visited this subject. I've just purchased a Windows tablet and was copying some programs to it. Something clicked and I realised how to achieve what I wanted without sub-editing and also to very simply restrict the number of characters into e Editbox.
I hope someone finds it useful.
Code: Select all
'=============================================
' NUMERIC INPUT IN AN EDITBOX
' File Name: NumericEntryIntoAnEditbox_WinGUI_2.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.
' It also allows the programmer to restrict the number of characters
' to be entered (including "-" and "."
' Code by RNBW.
'============================================
#Include "WinGUI.bi"
Dim As HWND Window_Main, Button_Ok, Edit_1
Dim As MSG msg
dim As String txt, oldtxt
Dim As Integer pos0
Function num(ByVal txt As String) As String
'Function to check that character input is 0-9, - or .
'The number of characters that can be entered will depend
'on the width of the Editbox and the size of the font.
'The Programmer is to check this and enter the maximum number
'of characters in the variable numChars
Dim As String num1
Dim As Integer i, a, t, maxNumChars
' enter the maximum number of characters to be entered and displayed
' in the Editbox.
' This will be dependent on the size of the Editbox and the size of font.
' The programmer will have to calculate this. I do it by simply typing in
' characters in the Editbox and counting them when it is full and not
' scrolling horizontally
maxNumChars = 12
For i = 1 To maxNumChars
a = Asc(Mid(txt,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 num1 = "0" + num1
If a = 45 Or a = 46 or a > 47 and a < 58 then num1 = num1 + Chr(a)
Next
a=asc(mid(txt,1,1))
if a = 45 and mid(txt,2,1) = "." then num1 = "-0" + num1
Return num1
End Function
'Create a window with an Editbox:
Window_Main = Window_New (100, 100, 400, 150, "Numeric Entry Filter!")
Var Label_txt = Label_New (10, 10, 150, 20, "Enter numbers:",, Window_Main)
Edit_1 = EditBox_New (150, 10, 100, 20, "", ES_RIGHT, Window_Main)
'Set timer to 300 miliseconds: increasingit is not eligible. this value shows the character entered
'and then removed if it is not eligible.
SetTimer(Window_Main, 0, 300, 0 )
Do
WaitEvent(Window_Main,msg)
Select Case msg.message
Case WM_TIMER
'Check contents of the edit box every 300 millisecinds
txt = EditBox_GetText(Edit_1) 'get text from edit box
oldtxt = txt 'make text the oldtext
txt = num(txt) 'gets new text from function num(txt) which does the checking
If oldtxt <> txt Then
EditBox_SetText(Edit_1, txt) 'if old text is not the same as the new text then use new text
pos0 = Len(txt) '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_Ok Then Print EditBox_GetText(Edit_1) 'print text to console
End Select
Loop Until Window_Event_Close(Window_Main, msg)
End