Numeric Entry in an EditBox
Re: Numeric Entry in an EditBox
Thanks, Josep, for spending time on this. Yes, that is the "logic" behind the mess. I was aware of the awkward concept of "a LONG_PTR is not a pointer", and yes, SetWindowLong is a tricky API because it eats pointers as well as scalars.
My feeling is that such strict (and confusing) type checking should not happen in a BASIC dialect. I have used such API calls since I started programming under Windows 20 years ago (before I was on an Atari ST and Motorola 68000, yet another story), and I never had a problem with the less stricter type checking of MASM. The latter throws an error if
- the parameter count is incorrect
- the size of a parameter is not correct
- you pass a DWORD instead of a REAL4 (and vice versa, of course)
Otherwise Masm assumes that you are able to read MSDN. I can't imagine that this shouldn't work with a Basic dialect. Sending a beginner in circles with monsters like PrevWinProc = CAST(ANY PTR, SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit))) is definitely not the right thing for a Beginners All purpose Symbolic Instruction Code ;-)
My feeling is that such strict (and confusing) type checking should not happen in a BASIC dialect. I have used such API calls since I started programming under Windows 20 years ago (before I was on an Atari ST and Motorola 68000, yet another story), and I never had a problem with the less stricter type checking of MASM. The latter throws an error if
- the parameter count is incorrect
- the size of a parameter is not correct
- you pass a DWORD instead of a REAL4 (and vice versa, of course)
Otherwise Masm assumes that you are able to read MSDN. I can't imagine that this shouldn't work with a Basic dialect. Sending a beginner in circles with monsters like PrevWinProc = CAST(ANY PTR, SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit))) is definitely not the right thing for a Beginners All purpose Symbolic Instruction Code ;-)
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: Numeric Entry in an EditBox
And the headers could have been more BASIC friendly by using BYREF for OUT parameters instead of BYVAL something PTR, etc., but this is what we have and isn't going to change.
Re: Numeric Entry in an EditBox
It's a while ago now, but I forgot that you had posted the above. It does get rid of the warning messages.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 read, with interest, the later discussions on scalars and pointers and the need for casting, and having come from a simpler programming background (most of which was many years ago) I found it very difficult to take in. No doubt I will in due course.
jj2007
I've been on the internet to try to find out more about subclassing and I'm afraid it's all gone completely over my head. I just can't take it in. I tried adjusting the code you provided to take into account the range of characters to be included in numeric entry and I'm sorry to say without success.
I think what it does call for is a FreeBasic tutorial on classes and sub-classes for we dummies and maybe my ever aging brain cells will take it in.
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: Numeric Entry in an EditBox
There is not need of a tutorial for something so simple.
Where hCtl is the handle of the control to subclass, uIdSubclass and identidier, e.g. 1, and dwRefData a pointer to reference data (can be NULL).
MSDN documentation:
SetWindowSubclass : https://docs.microsoft.com/en-us/window ... owsubclass
Subclassing Controls: https://docs.microsoft.com/en-us/window ... g-overview
Code: Select all
SetWindowSubclass hCtl, CAST(SUBCLASSPROC, @MySubclassProc), uIdSubclass, dwRefData
Code: Select all
' ========================================================================================
' Processes messages for the subclassed Button window.
' ========================================================================================
FUNCTION MySubclassProc ( _
BYVAL hwnd AS HWND, _ ' // Control window handle
BYVAL uMsg AS UINT, _ ' // Type of message
BYVAL wParam AS WPARAM, _ ' // First message parameter
BYVAL lParam AS LPARAM, _ ' // Second message parameter
BYVAL uIdSubclass AS UINT_PTR, _ ' // The subclass ID
BYVAL dwRefData AS DWORD_PTR _ ' // Pointer to reference data
) AS LRESULT
SELECT CASE uMsg
CASE WM_GETDLGCODE
' // All keyboard input
FUNCTION = DLGC_WANTALLKEYS
EXIT FUNCTION
' // ToDo: Process Windows messages
CASE WM_KEYDOWN
' ...
' ...
EXIT FUNCTION
CASE WM_DESTROY
' // REQUIRED: Remove control subclassing
RemoveWindowSubclass hwnd, @Button_SubclassProc, uIdSubclass
END SELECT
' // Default processing of Windows messages
FUNCTION = DefSubclassProc(hwnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
SetWindowSubclass : https://docs.microsoft.com/en-us/window ... owsubclass
Subclassing Controls: https://docs.microsoft.com/en-us/window ... g-overview
Re: Numeric Entry in an EditBox
JosepJosep Roca wrote:There is not need of a tutorial for something so simple.
Where hCtl is the handle of the control to subclass, uIdSubclass and identidier, e.g. 1, and dwRefData a pointer to reference data (can be NULL).Code: Select all
SetWindowSubclass hCtl, CAST(SUBCLASSPROC, @MySubclassProc), uIdSubclass, dwRefData
MSDN documentation:Code: Select all
' ======================================================================================== ' Processes messages for the subclassed Button window. ' ======================================================================================== FUNCTION MySubclassProc ( _ BYVAL hwnd AS HWND, _ ' // Control window handle BYVAL uMsg AS UINT, _ ' // Type of message BYVAL wParam AS WPARAM, _ ' // First message parameter BYVAL lParam AS LPARAM, _ ' // Second message parameter BYVAL uIdSubclass AS UINT_PTR, _ ' // The subclass ID BYVAL dwRefData AS DWORD_PTR _ ' // Pointer to reference data ) AS LRESULT SELECT CASE uMsg CASE WM_GETDLGCODE ' // All keyboard input FUNCTION = DLGC_WANTALLKEYS EXIT FUNCTION ' // ToDo: Process Windows messages CASE WM_KEYDOWN ' ... ' ... EXIT FUNCTION CASE WM_DESTROY ' // REQUIRED: Remove control subclassing RemoveWindowSubclass hwnd, @Button_SubclassProc, uIdSubclass END SELECT ' // Default processing of Windows messages FUNCTION = DefSubclassProc(hwnd, uMsg, wParam, lParam) END FUNCTION ' ========================================================================================
SetWindowSubclass : https://docs.microsoft.com/en-us/window ... owsubclass
Subclassing Controls: https://docs.microsoft.com/en-us/window ... g-overview
You are far far more proficient at coding than I am and what is clear and simple to you is, unfortunately, not to me. A tutorial with lots of examples would be very useful to knock it into me. For instance with the code that jj2007 provided, which he based on my code, he inserted a subclass and this did a check for characters greater than ASCII 57. I have tried to extend this to check for admissable characters with absolutely no success and because I don't understand the subclassing I don't know what I am doing wrong. I will continue trying but it is like working in a fog.
Re: Numeric Entry in an EditBox
If you post your code, I can look at it this evening. It's probably a minor issue.RNBW wrote:... ASCII 57. I have tried to extend this to check for admissable characters with absolutely no success and because I don't understand the subclassing I don't know what I am doing wrong.
All you have to do is:
- read the current text into a local buffer (WM_GETTEXT...)
- get the current cursor position inside the edit control (EM_GETSEL)
- decide if the char passed is admissible at this position; if not, set wp2 to zero to block it.
Re: Numeric Entry in an EditBox
The code is similar to that you posted for me earlier, but I have extended the wparam check.jj2007 wrote:If you post your code, I can look at it this evening. It's probably a minor issue.RNBW wrote:... ASCII 57. I have tried to extend this to check for admissable characters with absolutely no success and because I don't understand the subclassing I don't know what I am doing wrong.
All you have to do is:
- read the current text into a local buffer (WM_GETTEXT...)
- get the current cursor position inside the edit control (EM_GETSEL)
- decide if the char passed is admissible at this position; if not, set wp2 to zero to block it.
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 <45 or wParam = 47 or 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 = 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)
'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
Re: Numeric Entry in an EditBox
That was pretty close already. I've shortened it a little bit - tell me if it's OK now:RNBW wrote:The code is similar to that you posted for me earlier, but I have extended the wparam check.
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"
#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, @txt) ' let's get the current text
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=43 or wParam=45) and txtpos then wp2=0 ' +- only in pos 0
if wParam<>VK_BACK then
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)
SetFocus(Edit_1)
DO
WaitEvent(Window_Main,msg)
LOOP UNTIL Window_Event_Close(Window_Main, msg)
END
Re: Numeric Entry in an EditBox
THAT'S DONE IT. Thank you very much.jj2007 wrote:That was pretty close already. I've shortened it a little bit - tell me if it's OK now:RNBW wrote:The code is similar to that you posted for me earlier, but I have extended the wparam check.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" #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, @txt) ' let's get the current text 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=43 or wParam=45) and txtpos then wp2=0 ' +- only in pos 0 if wParam<>VK_BACK then 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) SetFocus(Edit_1) DO WaitEvent(Window_Main,msg) LOOP UNTIL Window_Event_Close(Window_Main, msg) END
I just needed to change
Code: Select all
SendMessage(hWnd, WM_GETTEXT, 1000, @txt)
Code: Select all
SendMessage(hWnd, WM_GETTEXT, 1000, cast (LONG_PTR,@txt))
I'll study your code now to see exactly how it works. Your help is very much appreciated.
-
- Posts: 1002
- Joined: Jul 14, 2005 23:41
Re: Numeric Entry in an EditBox
When dealing with SendMessage because the parameters are WPARAM and LPARAM, I've gotten into the habit of casting as follows (instead of LONG_PTR):SendMessage(hWnd, WM_GETTEXT, 1000, cast (LONG_PTR,@txt))
SendMessage(hWnd, WM_GETTEXT, 1000, cast (LPARAM,@txt))
Re: Numeric Entry in an EditBox
You can happily ignore that warning, it's a FreeBasic bug because WM_GETTEXT expects a pointer, not a scalar (Microsoft docs):RNBW wrote:I just needed to changetoCode: Select all
SendMessage(hWnd, WM_GETTEXT, 1000, @txt)
to get rid of the warning message about scalars.Code: Select all
SendMessage(hWnd, WM_GETTEXT, 1000, cast (LONG_PTR,@txt))
Code: Select all
lParam
A pointer to the buffer that is to receive the text
Last edited by jj2007 on Aug 28, 2018 19:14, edited 1 time in total.
Re: Numeric Entry in an EditBox
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.
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
Re: Numeric Entry in an EditBox
> txtpos=SendMessage(hWnd, EM_GETSEL, 0, 0) and 127
The and 127 just eliminates the HIWORD of the return value. In non-sloppy code, it would be and 65535 ;-)
The and 127 just eliminates the HIWORD of the return value. In non-sloppy code, it would be and 65535 ;-)
Re: Numeric Entry in an EditBox
Thank you for the explanation. Should I use 65535?jj2007 wrote:> txtpos=SendMessage(hWnd, EM_GETSEL, 0, 0) and 127
The and 127 just eliminates the HIWORD of the return value. In non-sloppy code, it would be and 65535 ;-)
Re: Numeric Entry in an EditBox
If you have a suspicion that a user might need more than 127 characters, use and 65535. In most cases, and 31 should be enough ;-)
A little variant that limits the input to 9 chars:
Code: Select all
EM_GETSEL: The return value is a zero-based 32-bit value with the starting position of the selection in the low-order word and the position of the first character after the last selected character in the high-order word.
Code: Select all
if uMsg=WM_CHAR and wParam<>VK_BACK then ' user typed something
if SendMessage(hWnd, WM_GETTEXT, 1000, @txt)>=9 then wp2=0 ' let's get the current text, and limit inputs to 9 bytes
if wParam>57 and wParam<>101 then ' definitely not a number (57="9") - but exponent is allowed (e=101)
wp2=0 ' letters etc not allowed
elseif wParam<48 then ' it's not a number (48="0")
if wParam=47 then wp2=0 ' / not allowed
txtpos=SendMessage(hWnd, EM_GETSEL, 0, 0) and 15 ' and the cursor position
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<43 or wParam=44 then wp2=0
endif