Hi,
new to ff and fb, been some years since I used basic, more recently been using c#. Is there an equivalent in ff/fb to key-up or key-down? For example, I want the user to be able to enter a value in textbox a, the program calculates, say half that value, and shows it in textbox b. or the user can enter value in b, and it shows twice that value in a. The ff functions seem to detect change in a text box (FF_TextBox_GetText) which does not seem to differentiate between a change made by the user, or made by the program. I do not want to use any 'enter button', or similar, would like the changes to be made on the fly. I'm sure there is a method somewhere, but can't quite get into the zone...
Best wishes,
Ray
Hi Ray,
Your question sounds very similar to the one I emailed to you several days ago. FireFly is a WinAPI based visual designer meaning that you need to understand (or know where to research) how the Windows API works. For TextBoxes (or more technically correct, Edit controls), certain notifications get sent to the parent of the control to inform the programmer that something has happened. You simply need to know what these notifications mean and then respond to them from within the FireFly editor.
When text gets changed in a TextBox, the control sends a EN_UPDATE to the parent form notifying it of the change. Here is the EN_CHANGE documentation: https://msdn.microsoft.com/en-us/library/windows/desktop/bb761676(v=vs.85).aspx
FireFly makes it easy to deal with these messages. Say you have a TextBox (called txtEntry) on a Form (called Form1) you only need to select the EN_UPDATE message for the txtEntry TextBox and type your code into the editor.
'--------------------------------------------------------------------------------
Function FORM1_TXTENTRY_EN_CHANGE ( _
ControlIndex as Long, _ ' index in Control Array
hWndForm as HWnd, _ ' handle of Form
hWndControl as HWnd, _ ' handle of Control
idTextControl as Long _ ' identifier of text control
) as Long
' Simply get the text from the top textbox (TXTENTRY) and put it
' into the bottom textbox (TXTVALIDATE)
Dim as String sText = FF_TextBox_GetText(hWndControl)
' Or you could also use the global window handle variable for this textbox (press F4 to see these variables)
'Dim as String sText = FF_TextBox_GetText(HWND_FORM1_TXTENTRY)
' Now copy the text into the bottom textbox.
FF_TextBox_SetText(HWND_FORM1_TXTVALIDATE, sText)
Function = 0 ' change according to your needs
End Function
You could do the same thing for your second TextBox (called txtValidate). Just respond to that TextBox's EN_CHANGE message, do your calculations, and update the first TextBox.
Thanks, Paul, it is indeed similar, but I think the problem I'm getting is that the EN_Change notification, according to M$, is sent after the system updates the screen. I'm guessing that is whether it is updated by the program, or the user. (Well, it's got to be the program, unless the user uses a sharpie, I guess)
I have been experimenting with a sort of toggle, to check if last update was by the program, or the user, which almost works as I want it to, but the cursor resets to the start of the textbox, which is not what I want. (Also a problem with one of the textboxes, the cursor does not line up with said box, quite a few pixels below, but that is unrelated, afaik with this initial question).
I think I'll start yet again, and if it doesn't work, I'll post the code here with a more detailed explanation. Too much arbitrary trace code in what I have arrived at so far.
Best wishes,
Ray
Hi Ray, without seeing your code it is of course hard to know exactly where the problem is. It could be that you are getting the EN_CHANGE once when the Form is created but prior to being shown. Take a look at this post I made many years ago: http://www.planetsquires.com/protect/forum/index.php?topic=2502.msg19167#msg19167
If all you are trying to do is filter keypresses before they even make it to the TextBox then you can intercept them in WM_CHAR or WM_KEYUP. Check out posts like these:
http://www.planetsquires.com/protect/forum/index.php?topic=2916.msg21686#msg21686
http://www.planetsquires.com/protect/forum/index.php?topic=3695.msg27179#msg27179
http://www.planetsquires.com/protect/forum/index.php?topic=3422.msg24909#msg24909
...and if you don't want to create a filter in every single TextBox's message handler, then you can modify FF_PUMPHOOK to catch keypresses going to whatever TextBoxes you need and discard them as required.
Thanks, I'll read your references. I've just written out the basic spec of what I'm attempting. Sounds like a homework question, I guess it is, 'cos I'm at home, but I'm trying to have fun...
description, three text boxes, A, B, C
entries in any box can be altered by the user at any time.
text box A is a multiplying factor, say.
so, user enters a value in A, textbox C is changed by program, to B*A
user enters value in B, A is unchanged, program alters C to B*A
user enters value in C, A is unchanged, program alters B to C/A
The values in the appropiate text boxes change as each character is typed by the user (assuming only dealing with valid numbers here).
Best wishes,
Ray
Sounds like a great exercise to learn the basic internals of how FireFly handles the flow of messages. We're here to help guide you should you need help :)
Expanding on that concept of data entry/display without an 'enter' key, I tried writing an app for the windows phone in C#, the software worked fine, but I despaired of M$ phone ethos, no wonder there are few window phone apps. I got it working in a clunky fashion using javascript, but didn't like the graphics, nor javascript. Then I gave up the phone idea. Recently I bought a little Acer tablet, for not much money. It runs 32bit W10, and I thought I would have a go at rewriting it in something that did not require .net, and hopefully would compile to just a small exe.. I tried Vbasic for dos, but that wouldn't run on the tablet, so that is where I'm at now, having to try and relearn basic/whatever from 50 odd years ago, as well as the firefly stuff. It's much more complicated now.
OK, here's some code - the graphics is just a form with three text boxes named a, b, c. (initialise their text to '1', say). I have a vague idea of what is happening, I think I need to somehow detect the user entering text, and then suppress the sort of tail chasing updating between textbox b and c. (The print statements are to add a simple trace). I would like the user data entry to be as in textbox a, but what happens now is that the others get re-written, cursor moved each time on entry, and it is awkward, to say the least, to enter a decimal point number in b or c. There is something pretty basic, I expect I've missed out completely. I have tried various other solutions, but this is the starting point.
Thanks,
Ray
'entries in Any box can be altered by the user at Any Time.
'text box A Is a multiplying factor, say.
'
'so, user enters a Value in A, textbox C Is changed by program, To B*A
'user enters Value in B, A Is unchanged, program alters C To B*A
'user enters Value in C, A Is unchanged, program alters B To C/A
'
'The values in the appropiate text boxes change as each character Is typed by the user (assuming only dealing With valid numbers here).
Dim Shared av as Double =1
Dim Shared bv as Double =1
Dim Shared cv as Double =1
'--------------------------------------------------------------------------------
Function FORM1_WM_CREATE ( _
hWndForm as HWnd, _ ' handle of Form
ByVal UserData as Integer _ ' optional user defined value
) as Long
Function = 0 ' change according to your needs
End Function
'--------------------------------------------------------------------------------
Function FORM1_C_EN_CHANGE ( _
ControlIndex as Long, _ ' index in Control Array
hWndForm as HWnd, _ ' handle of Form
hWndControl as HWnd, _ ' handle of Control
idTextControl as Long _ ' identifier of text control
) as Long
'change b to cv/av (read c)
cv=Val(FF_TextBox_GetText(hwndcontrol))
bv=cv/av
FF_TextBox_SetText( hwnd_form1_b, Str (bv ) )
Print av,bv,cv ,"from c"
Function = 0 ' change according to your needs
End Function
'--------------------------------------------------------------------------------
Function FORM1_B_EN_CHANGE ( _
ControlIndex as Long, _ ' index in Control Array
hWndForm as HWnd, _ ' handle of Form
hWndControl as HWnd, _ ' handle of Control
idTextControl as Long _ ' identifier of text control
) as Long
' change c To av *bv (Read b)
bv=Val(FF_TextBox_GetText(hwndcontrol))
cv=av*bv
FF_TextBox_SetText( hwnd_form1_c, Str (cv ) )
Print av,bv,cv ,"from b"
Function = 0 ' change according to your needs
End Function
'--------------------------------------------------------------------------------
Function FORM1_A_EN_CHANGE ( _
ControlIndex as Long, _ ' index in Control Array
hWndForm as HWnd, _ ' handle of Form
hWndControl as HWnd, _ ' handle of Control
idTextControl as Long _ ' identifier of text control
) as Long
' change c to av *bv (read a)
av = Val(FF_TextBox_GetText( hWndControl))
cv = av*bv
FF_TextBox_SetText( hwnd_form1_c, Str (cv ) )
Print av,bv,cv ,"from a"
Function = 0 ' change according to your needs
End Function
Edit: Added code tags
Here is one way to do it. You need to suppress the firing of EN_CHANGE when the text is being set otherwise there will be a lot of cascading of EN_CHANGE messages.
'entries in Any box can be altered by the user at Any Time.
'text box A Is a multiplying factor, say.
'
'so, user enters a Value in A, textbox C Is changed by program, To B*A
'user enters Value in B, A Is unchanged, program alters C To B*A
'user enters Value in C, A Is unchanged, program alters B To C/A
Dim Shared gIsProcessing as BOOLEAN
'--------------------------------------------------------------------------------
Function FORM1_WM_CREATE ( _
hWndForm as HWnd, _ ' handle of Form
ByVal UserData as Integer _ ' optional user defined value
) as Long
FF_TextBox_SetText( HWND_FORM1_A, "100" )
Function = 0 ' change according to your needs
End Function
'--------------------------------------------------------------------------------
Function FORM1_A_EN_CHANGE ( _
ControlIndex as Long, _ ' index in Control Array
hWndForm as HWnd, _ ' handle of Form
hWndControl as HWnd, _ ' handle of Control
idTextControl as Long _ ' identifier of text control
) as Long
' change c to av *bv (read a)
Dim as Double av = Val(FF_TextBox_GetText(HWND_FORM1_A))
Dim as Double bv = Val(FF_TextBox_GetText(HWND_FORM1_B))
Dim as String cv = Str(av*bv)
FF_TextBox_SetText( HWND_FORM1_C, cv )
Print av,bv,cv ,"from a"
Function = 0 ' change according to your needs
End Function
'--------------------------------------------------------------------------------
Function FORM1_B_EN_CHANGE ( _
ControlIndex as Long, _ ' index in Control Array
hWndForm as HWnd, _ ' handle of Form
hWndControl as HWnd, _ ' handle of Control
idTextControl as Long _ ' identifier of text control
) as Long
If gIsProcessing Then Exit Function
' change c To av * bv (Read b)
Dim as Double av = Val(FF_TextBox_GetText(HWND_FORM1_A))
Dim as Double bv = Val(FF_TextBox_GetText(HWND_FORM1_B))
Dim as String cv = Str(av*bv)
' Must prevent the firing of the EN_CHANGE message for textbox C
gIsProcessing = True
FF_TextBox_SetText( HWND_FORM1_C, cv )
gIsProcessing = False
Print av,bv,cv ,"from b"
Function = 0 ' change according to your needs
End Function
'--------------------------------------------------------------------------------
Function FORM1_C_EN_CHANGE ( _
ControlIndex as Long, _ ' index in Control Array
hWndForm as HWnd, _ ' handle of Form
hWndControl as HWnd, _ ' handle of Control
idTextControl as Long _ ' identifier of text control
) as Long
If gIsProcessing Then Exit Function
'change b to cv/av (read c)
Dim as Double av = Val(FF_TextBox_GetText(HWND_FORM1_A))
Dim as Double cv = Val(FF_TextBox_GetText(HWND_FORM1_C))
Dim as String bv = Str(cv/av)
' Must prevent the firing of the EN_CHANGE message for textbox B
gIsProcessing = True
FF_TextBox_SetText( HWND_FORM1_B, bv )
gIsProcessing = False
Print av,bv,cv ,"from c"
Function = 0 ' change according to your needs
End Function
Thanks, that was what I was trying to do, but I didn't know how. A bit late/early here, I'll have a try with the new code later today.
Thanks, simple when you know how. My approach, had led me down a rabbit hole. You read both values and calculate the third based on the values just read, whereas for my previous attempts (not shown) I read only one value, and calculated based on that and one other from the stored variables. I was looking at separating user data entry from program data entry, whereas you've stopped recalculation when any data is being written, whether by user or program.
I can now expand this, to get to what I want to do, thanks.
btw, is there a post processor or something that I can feed in the program text file to get it neatly laid out? Or have I got to train myself?
Best wishes,
Ray
Quote from: raymw on January 23, 2017, 07:59:30 AM
btw, is there a post processor or something that I can feed in the program text file to get it neatly laid out? Or have I got to train myself?
There is nothing built into Firefly that does automatic code formatting. Like you say, I have trained myself to lay out my code how I prefer it (indentation, spacing, capitalization, etc...)