By subclassing the edit control.RNBW wrote: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.
Numeric Entry in an EditBox
Re: Numeric Entry in an EditBox
Re: Numeric Entry in an EditBox
Looking back at your earlier post on subclassing.jj2007 wrote:By subclassing the edit control.RNBW wrote: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.
Re: Numeric Entry in an EditBox
I've played around with the code you gave in an earlier posting and must admit I don't fully understand it. I've looked around to see if I can get some help online with subclassing in Freebasic with not much success. Can you extend the code you gave a little to give me more of a pointer.jj2007 wrote:By subclassing the edit control.RNBW wrote: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.
I've also had a look at http://masm32.com/board/index.php?topic ... 5#msg79165 and downloaded the code and executable. I've run the executable, which does exactly what I want (with one exception, editing the number you can place more than one minus sign at the start of the number e.g. I was able to edit -0.123 with the result -0.123 to ---0.123 with the result 0.0 by successively typing a minus at the very beginning of the number entry). With respect to the code, I have no experience of assembler code so haven't a clue as to how it works.
Re: Numeric Entry in an EditBox
The line PrevWinProc=SetWindowLongPtr(Edit_1, GWLP_WNDPROC, @SubEdit) tells the OS that from now on, before doing the default processing of messages, Windows passes by the callback SUB SubEdit. This is a user-defined SUB which receives all messages sent by the OS,together with their wParam and lParam.
We are only interested in the WM_CHAR message:Normally, we ignore the messages and pass them on to Windows via CallWindowProc. However, if we don't like the CHAR passed (e.g. everything above Ascii 57), we set wp2 to zero, so that CallWindowProc passes a null char. The edit control doesn't know what to do with a null char and therefore ignores it completely.
The two prints are for debugging, as you can imagine. What is still needed is the logic which determines whether the char "+" or "x" should be allowed to pass or not. So you need to get the text, determine the current position, and decide whether to allow the char or block it.
Let me know if something is not clear.
We are only interested in the WM_CHAR message:
Code: Select all
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
The two prints are for debugging, as you can imagine. What is still needed is the logic which determines whether the char "+" or "x" should be allowed to pass or not. So you need to get the text, determine the current position, and decide whether to allow the char or block it.
Let me know if something is not clear.
Re: Numeric Entry in an EditBox
jj2007
Just running through your code to see what happens and I get 2 warnings both associated with
1.. warning 2(1): Passing pointer to scalar, at parameter 3 of SETWINDOWLONGPTR()
2.. warning 4(1): Suspicious pointer assignment
I don't know if this has any significance. It doesn't stop Compilation/Execute, but does stop Quickrun.
Just running through your code to see what happens and I get 2 warnings both associated with
Code: Select all
PrevWinProc=SetWindowLongPtr(Edit_1, GWLP_WNDPROC, @SubEdit)
2.. warning 4(1): Suspicious pointer assignment
I don't know if this has any significance. It doesn't stop Compilation/Execute, but does stop Quickrun.
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: Numeric Entry in an EditBox
You have to do the appropriate casts, e.g. (for the Passing pointer to scalar warning)
PrevWinProc=SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit))
PrevWinProc=SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit))
Re: Numeric Entry in an EditBox
Josep's solution will certainly remove these warnings. Fb exaggerates the type checking, the args are perfectly valid.
Re: Numeric Entry in an EditBox
See the post I just sent: viewtopic.php?p=251125#p251125
Re: Numeric Entry in an EditBox
That still gives a warning 4(1): Suspicious pointer assignment. I find this kind of wrong type checking really exaggerated. Why do I need a CAST(SOME_TYPE_OF_POINTER, @Whatever) when it's crystal clear that the ampersand denotes a POINTER...? This is C++ BS, not Basic.Josep Roca wrote:You have to do the appropriate casts, e.g. (for the Passing pointer to scalar warning)
PrevWinProc=SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit))
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: Numeric Entry in an EditBox
> That still gives a warning 4(1): Suspicious pointer assignment.
SetWindowLongPtr returns a long in 32 bit and a LONG_PTR (not a pointer, but a LONGINT) in 64 bit, and it is being assigned to a variable declared as ANY PTR. So you need another cast.
With Free Basic, you cant write sloppy code that passes pointers to scalars and scalars to pointers without casting.
SetWindowLongPtr returns a long in 32 bit and a LONG_PTR (not a pointer, but a LONGINT) in 64 bit, and it is being assigned to a variable declared as ANY PTR. So you need another cast.
With Free Basic, you cant write sloppy code that passes pointers to scalars and scalars to pointers without casting.
Re: Numeric Entry in an EditBox
It returns a pointer to the old wndproc, and expects as arg a pointer to the new wndproc.
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: Numeric Entry in an EditBox
> It returns a pointer to the old wndproc
But not as a pointer variable but as a scalar.
Try
PrevWinProc = CAST(ANY PTR, SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit)))
But not as a pointer variable but as a scalar.
Try
PrevWinProc = CAST(ANY PTR, SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit)))
Re: Numeric Entry in an EditBox
Dim shared as any ptr PrevWinProc ' warning 4(1): Suspicious pointer assignment
Dim shared as LONG_PTR PrevWinProc ' warning 1(1): Passing scalar as pointer, at parameter 1 of CALLWINDOWPROC()
PrevWinProc = CAST(ANY PTR, SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit)))
a) with Dim shared as LONG_PTR PrevWinProc ' warning 5(0): Implicit conversion
b) with Dim shared as any ptr PrevWinProc: "OK"
This is really sick! I have no other word for this nonsense. A pointer is a pointer, there is no ambiguity. And SetWindowLongPtr points the OS to a new WndProc.
Dim shared as LONG_PTR PrevWinProc ' warning 1(1): Passing scalar as pointer, at parameter 1 of CALLWINDOWPROC()
PrevWinProc = CAST(ANY PTR, SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit)))
a) with Dim shared as LONG_PTR PrevWinProc ' warning 5(0): Implicit conversion
b) with Dim shared as any ptr PrevWinProc: "OK"
This is really sick! I have no other word for this nonsense. A pointer is a pointer, there is no ambiguity. And SetWindowLongPtr points the OS to a new WndProc.
Re: Numeric Entry in an EditBox
Or (only user parameters are converted):
Cast(LONG_PTR, PrevWinProc) = SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit))
Cast(LONG_PTR, PrevWinProc) = SetWindowLongPtr(Edit_1, GWLP_WNDPROC, CAST(LONG_PTR, @SubEdit))
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: Numeric Entry in an EditBox
I don't see any nonsense, although I agree that strict type casting can be very annoying sometimes. With other compilers such PowerBasic, with relaxed type casting, some complain that the compiler does not warn them when they pass an scalar by mistake to a function that expects a pointer.This is really sick! I have no other word for this nonsense. A pointer is a pointer, there is no ambiguity. And SetWindowLongPtr points the OS to a new WndProc.
Because SetWindowLongPtr is not limited to work with pointer values, but also allows to use scalars, for example to store scalar values in the user data of the control, the third parameter and the return value haven't been declared as pointer but as scalars. Don't forget that the original function name was SetWindowLong (without the "Ptr" part, that was added latter, with 64 bit, to avoid a name conflict). Therefore, the function expects a LONG in 32 bit and a LONGINT in 64 bit, which can also be pointer values because they are the same size.
Code: Select all
declare function SetWindowLongPtr alias "SetWindowLongA"(byval hWnd as HWND, byval nIndex as long, byval dwNewLong as LONG) as LONG
declare function SetWindowLongPtr alias "SetWindowLongPtrA"(byval hWnd as HWND, byval nIndex as long, byval dwNewLong as LONG_PTR) as LONG_PTR
Therefore, when you use @SubEdit, you are passing a pointer to a parameter declared as LONG, and the compiler warns about passing a wrong type, and when you do "PrevWinProc =", that has been declared as ANY PTR, you are assigning a LONG value to a pointer variable, and the compiler complains about "Implicit conversion", so it needs a "CAST(ANY PTR, " to supress the warning. If you declare PrevWinProc as LONG_PTR, then you don't have to use "CAST(ANY PTR, ".
So it can be annoying, but it makes sense. If Microsodt diden't have tried to use the same function to work both with scalars and pointers they will have avoided this mess. They could have implemented SetWindowLong to work with scalars and SetWindowLongPtr to work with pointers.