hal9k
Junior Member
Posts: 87
|
Post by hal9k on Aug 28, 2022 12:56:13 GMT -5
Here's another dumb question. I have a window with 91 Textboxes that the user can change. A Save button and a Cancel button determine whether I update my data file with the new values or just quit the program.
It would be great if there was a way for me to know WHICH Textboxes were changed. I can't find a way to do that. Does anybody have a way around this?
Failing that, I have another question. I don't know how LB buffers Put commands. Is it better to do 91 If commands with 1 or 2 of them triggering a Put statement or is it better to just do the 91 Put statements regardless of whether the Textboxes have changed?
Thanks yet again!
|
|
|
Post by Rod on Aug 28, 2022 13:44:33 GMT -5
As you are learning once you expose your system to users anything that can go wrong will. I would go for the 91 put statements but with some validation on the contents. The traditional way is to trap the contents on opening to an array and to use that array against the closing contents to know if a change has been made. Validation is the key for me. Free text would be a nightmare, list box choice of a restricted text set is by far the safest.
|
|
hal9k
Junior Member
Posts: 87
|
Post by hal9k on Aug 28, 2022 14:02:01 GMT -5
That's pretty much what I'm coding. I'm expecting numbers. If the new contents are not numeric or wildly out of range I'm resetting it to the original value. I assumed the Puts are buffered such that there's probably only a single disk write rather than 91 of them.
Thanks.
|
|
|
Post by Rod on Aug 28, 2022 14:26:07 GMT -5
Windows OS takes care of the put statement. All file activity is buffered to ram for speed. But Windows makes a pretty good job of this buffering. It never gets out of sync.
|
|
|
Post by Walt Decker on Aug 28, 2022 15:33:57 GMT -5
Mr. Pryor, there is a way; however, with a textbox you will have to use an API call to do it. To find if the edit control has changed use:
EM.GETMODIFY = HEXDEC("&H00B8") Determine whether the content of an edit control has been modified.
wParam = 0 <--- not used; must be zero lParam = 0 <--- not used; must be zero
RETURN: If the content of edit control has been modified, the return value is TRUE; otherwise, it is FALSE.
NOTES: Windows maintains an internal flag indicating whether the content of the edit control has been changed. This flag is cleared when the edit control is first created; alternatively, an application can send an EM.SETMODIFY message to the edit control to clear the flag.
CALLDLL #user32, "SendMessageA", EdtHndl AS ULONG, EM.GETMODIFY AS ULONG, 0 AS LONG, 0 AS LONG, Modifyed AS LONG
Normally, the output is buffered, therefore writing 91 "PUTS" will write the data at one shot. However, depending of the programming system and whether you use API code to output and/or input data, than may not always be the case.
|
|
hal9k
Junior Member
Posts: 87
|
Post by hal9k on Aug 28, 2022 16:16:59 GMT -5
Thanks Mr. Decker. Using the API call it looks like I would still need to do 91 IF statements to test all the Textboxes. So, I think I'll just plow ahead with the 91 Puts. It's in a loop, so it's just a couple of lines of code.
Thanks again!
|
|
|
Post by Walt Decker on Aug 28, 2022 16:55:20 GMT -5
No. Only one if:
Ctl$ = "mywin.txb" Holder$ = "" DIM CtlHndls(90) Elm = -1 FOR I = 1 TO 91 Elm = Elm + 1 Holder$ = Ctl$ + STR$(I) CtlHndls(Elm) = HWND(#Holder$) NEXT I
'<======== OTHER CODE =========>
SUB BUTTON.CLICK BtnHndl$
EM.GETMODIFY = HEXDEC("&H00B8") FOR I = 0 TO 90 EdtHndl = CtlHndls(I) CALLDLL #user32, "SendMessageA", EdtHndl AS ULONG, EM.GETMODIFIED AS ULONG, _ 0 AS LONG, 0 AS LONG, Modified AS LONG IF Modified THEN '<==== Do Something =====> END IF NEXT I END SUB
|
|
hal9k
Junior Member
Posts: 87
|
Post by hal9k on Aug 29, 2022 9:57:12 GMT -5
Very nice. Thanks!
|
|
|
Post by Walt Decker on Aug 29, 2022 17:44:40 GMT -5
Mr. Pryor, here is something in which you may be interested: ' Mask = HEXDEC("&H8000") '<--- Mask value for GetAsyncKeyState()
VK.RETURN = HEXDEC("&H0D") '<--- virtual key codes of interest VK.TAB = HEXDEC("&H09")
ES.WANTRETURN = HEXDEC("&H1000") '<--- edit control styles ES.MULTILINE = HEXDEC("&H0004") ES.NOHIDESEL = HEXDEC("&H0100")
[DEF.GLOBALS] GLOBAL EM.GETMODIFY, _ '<--- edit control messages EM.SETMODIFY
GLOBAL Ubnd '<--- # of elements in TxbHndls$()
DIM TxbHndls$(2, 2)
[INIT.GLOBALS] EM.GETMODIFY = HEXDEC("&H00B8") EM.SETMODIFY = HEXDEC("&H00B9")
Ubnd = 2
OPEN "User32.dll" FOR DLL AS #USER '<--- could use #user32 instead
[DEF.CONTROLS] '<--- set edit control style '########################################################################### ' If the TIMER AND THE [CHECK.ENTER] block is not used do not change ' the edit control style. '###########################################################################
STYLEBITS #DMO.TXB0, ES.MULTILINE OR ES.WANTRETURN OR ES.NOHIDESEL, 0, 0, 0 STYLEBITS #DMO.TXB1, ES.MULTILINE OR ES.WANTRETURN OR ES.NOHIDESEL, 0, 0, 0 STYLEBITS #DMO.TXB2, ES.MULTILINE OR ES.WANTRETURN OR ES.NOHIDESEL, 0, 0, 0 TEXTBOX #DMO.TXB0, 5, 5, 100, 25 TEXTBOX #DMO.TXB1, 110, 5, 100, 25 TEXTBOX #DMO.TXB2, 215, 5, 100, 25
BUTTON #DMO.APPLY, "APPLY", BTN.APPLY, UL, 120, 35, 60, 25
WindowWidth = 335 OPEN "TEXTBOX DEMO" FOR WINDOW AS #DMO
'<------- save the edit control handles and names for later use -------> Ctl$ = "#DMO.TXB" Tmp$ = ""
FOR I = 0 TO 2 Tmp$ = Ctl$ + STR$(I) TxbHndls$(I, 0) = STR$(HWND(#Tmp$)) TxbHndls$(I, 1) = Tmp$ NEXT I
PRINT #DMO.TXB0, "!SETFOCUS" PRINT #DMO, "TRAPCLOSE END.DMO"
CurFocus = 0 '<--- set the current element of TxbHndls$()
[BEGIN.WAIT] TIMER 150, [CHECK.ENTER] '<--- set up timer event WAIT
[CHECK.ENTER] TIMER 0
ReturnKey = 0 '<--- virtual key of interest
HasFocus = 0 '<--- edit control with focus RetVal = 0 '<--- return value from function calls
Tmp$ = "" '<--- temporary string
CtlHndl = VAL(TxbHndls$(CurFocus, 0)) '<--- handle of edit control
'############################################# ' The GetAsyncKeyState() function returns the state of the ' virtual key of interest since the LAST TIME THE FUNCTION ' WAS CALLED. You should always mask out the return value ' instead of just quering whether the return value is true of ' or fales. '#############################################
CALLDLL #USER, "GetAsyncKeyState", VK.RETURN AS LONG, ReturnKey AS SHORT ReturnKey = ReturnKey AND Mask CALLDLL #USER, "GetFocus", HasFocus AS ULONG
IF HasFocus <> CtlHndl THEN RetVal = FN.FindFocus(HasFocus, Ubnd, 0) '<--- which contol has the focus
IF RetVal < 0 THEN GOTO [BEGIN.WAIT] '<--- something other than an edit 'has the focus
CurFocus = RetVal '<--- set the element of TxbHndls$() END IF
IF ReturnKey THEN '<--- ENTER key was pressed CurFocus = CurFocus + 1 '<--- set the element of TxbHndls$() IF CurFocus > Ubnd THEN CurFocus = 0
Tmp$ = TxbHndls$(CurFocus, 1) PRINT #Tmp$, "!SETFOCUS" '<--- set the focus END IF GOTO [BEGIN.WAIT] [END.CHECK.ENTER]
'-------------------------------------- '--------------------------------------
SUB BTN.APPLY BtnHndl$
Modified = 0 CtlHndl = 0
'<--- parse the TxbHndls$() array and obtain the change ---> '<--- state of each edit control ----> FOR I = 0 TO Ubnd CtlHndl = VAL(TxbHndls$(I, 0)) CALLDLL #USER, "SendMessageA", CtlHndl AS ULONG, EM.GETMODIFY AS ULONG, _ 0 AS LONG, 0 AS LONG, Modified AS LONG IF Modified THEN TxbHndls$(I, 2) = "M" '<--- perhaps do something else here END IF NEXT I
CALL END.DMO "#DMO" END SUB
'-------------------------------------- '--------------------------------------
SUB END.DMO DmoHndl$
FOR I = 0 TO Ubnd PRINT TxbHndls$(I, 1); " ";TxbHndls$(I, 2) NEXT I
CLOSE #USER CLOSE #DmoHndl$ END
END SUB
'---------------------------------- '----------------------------------
FUNCTION FN.FindFocus(Focus, Ubnd, Elm)
Found = 0 FOR I = 0 TO Ubnd IF Focus = VAL(TxbHndls$(I, Elm)) THEN Found = I EXIT FOR END IF NEXT I
IF Found THEN FN.FindFocus = Found EXIT FUNCTION END IF
FN.FindFocus = -1
END FUNCTION '[code]
|
|
hal9k
Junior Member
Posts: 87
|
Post by hal9k on Aug 29, 2022 17:59:43 GMT -5
Thanks again. Sadly the project was cancelled, but I'll keep this code in mind as I may need it for a future project.
|
|
|
Post by Brandon Parker on Sept 2, 2022 18:20:25 GMT -5
Also, you can also add the _ES_NUMBER StyleBit to a TextBox to allow only numbers to be typed into the TextBox. This would prevent the use of negative numbers as well as the decimal character. Also, note that this StyleBit does not prevent pasting other characters into the TextBox.
You could, using something like WMLiberty.dll, trap the WM_CHAR message and allow whatever you wanted through.
Just some things to think about for future projects...
{:0)
Brandon Parker
|
|